HDU 3911 区间合并求最大长度的问题
http://vjudge.net/problem/viewProblem.action?id=21557
题目大意:
每进行一次颜色改变都可以把一段区间内的黑石头变成白石头,白石头变成黑石头,最后问区间内黑石头连续的最大长度
这里我们可以用rev[]作为lazy标记,每次进行改变,rev[]^1
因为有黑白两种石头,我们求连续区间,需要维护黑,白两种石头的左侧最多,右侧最多和全部最多,所以我们这里可以用一个二维数组进行描述
每次做出改变,只要将黑白石头的值进行交换即可就方便了很多
对于最后访问的时候做的区间合并。。。。我确实有点拙计了,最后是学长帮忙改正的。。。。
还是有点只会套模板的嫌疑Orz,关键模板的代码是不考虑处在两个不同的区间进行合并的情况的,所以最后在所有 单个区间的情况判断完后,我们
要把左子树的右侧和右子树的左侧合并到一起,因为可能会超过访问范围,所以这里用的是:
ans = max(ans,min(mid-s+1,rc[ls][1])+min(t-mid,lc[rs][1]));
在内部取个最小值。
在此将自己拙计的query函数和正确的query函数进行一下对比:
/*
void query(int cur ,int x,int y,int s,int t,int &ans)
{
int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1;
if(x>=s&&y<=t){
ans+=mc[cur][1];
return;
}
push_down(cur,x,y);
if(mid>=s) query(L,s,t,ans);
if(mid+1<=t) query(R,s,t,ans);
}*/ int query(int cur,int x,int y,int s,int t){
int mid=(x+y)/,ls=cur<<,rs=cur<<|;
if(x>=s&&y<=t){
return mc[cur][];
}
push_down(cur,x,y);
int ans = ;
if(mid>=s) ans = max(ans,query(L,s,t));
if(mid+<=t) ans = max(ans,query(R,s,t));
ans = max(ans,min(mid-s+,rc[ls][])+min(t-mid,lc[rs][]));
return ans;
}
总代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 100010
#define L ls,x,mid
#define R rs,mid+1,y
int color[N],rev[N<<],lc[N<<][],rc[N<<][],mc[N<<][];
void push_up(int cur,int x,int y)
{
int mid=(x+y)/,ls=cur<<,rs=cur<<|;
for(int i=;i<;i++){
lc[cur][i]=lc[ls][i],rc[cur][i]=rc[rs][i];
mc[cur][i]=max(mc[ls][i],mc[rs][i]);
mc[cur][i]=max(mc[cur][i],rc[ls][i]+lc[rs][i]);
if(lc[ls][i]==mid-x+) lc[cur][i]=lc[ls][i]+lc[rs][i];
if(rc[rs][i]==y-mid) rc[cur][i]=rc[rs][i]+rc[ls][i];
}
}
void push_down(int cur,int x,int y)
{
int ls=cur<<,rs=cur<<|;
if(rev[cur]){
rev[ls]^=,rev[rs]^=; swap(lc[ls][],lc[ls][]);
swap(lc[rs][],lc[rs][]); swap(rc[ls][],rc[ls][]);
swap(rc[rs][],rc[rs][]); swap(mc[ls][],mc[ls][]);
swap(mc[rs][],mc[rs][]); rev[cur]=;
}
}
void build(int cur,int x,int y)
{
int mid=(x+y)/,ls=cur<<,rs=cur<<|;
rev[cur]=;
if(x==y){
lc[cur][]=rc[cur][]=mc[cur][]=color[x]^;
lc[cur][]=rc[cur][]=mc[cur][]=color[x];
return;
}
build(L);
build(R);
push_up(cur,x,y);
}
void update(int cur,int x,int y,int s,int t)
{
int mid=(x+y)/,ls=cur<<,rs=cur<<|;
if(x>=s&&y<=t){
swap(lc[cur][],lc[cur][]);
swap(rc[cur][],rc[cur][]);
swap(mc[cur][],mc[cur][]);
rev[cur]^=;
return;
}
push_down(cur,x,y);
if(mid>=s) update(L,s,t);
if(mid+<=t) update(R,s,t);
push_up(cur,x,y);
}
/*
void query(int cur ,int x,int y,int s,int t,int &ans)
{
int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1;
if(x>=s&&y<=t){
ans+=mc[cur][1];
return;
}
push_down(cur,x,y);
if(mid>=s) query(L,s,t,ans);
if(mid+1<=t) query(R,s,t,ans);
}*/ int query(int cur,int x,int y,int s,int t){
int mid=(x+y)/,ls=cur<<,rs=cur<<|;
if(x>=s&&y<=t){
return mc[cur][];
}
push_down(cur,x,y);
int ans = ;
if(mid>=s) ans = max(ans,query(L,s,t));
if(mid+<=t) ans = max(ans,query(R,s,t));
ans = max(ans,min(mid-s+,rc[ls][])+min(t-mid,lc[rs][]));
return ans;
}
int main()
{
int n,m,op,a,b;
while(scanf("%d",&n)!=EOF){
for(int i=;i<=n;i++) scanf("%d",&color[i]);
build(,,n);
scanf("%d",&m);
for(int i=;i<m;i++){
scanf("%d%d%d",&op,&a,&b);
if(op) update(,,n,a,b);
else{
//int ans=0;
//query(1,1,n,a,b,ans);
printf("%d\n",query(,,n,a,b));
}
}
}
return ;
}
HDU 3911 区间合并求最大长度的问题的更多相关文章
- Tunnel Warfare HDU 1540 区间合并+最大最小值
Tunnel Warfare HDU 1540 区间合并+最大最小值 题意 D x是破坏这个点,Q x是表示查询以x所在的最长的连续的点的个数,R是恢复上一次破坏的点. 题解思路 参考的大佬博客 这里 ...
- E - Tunnel Warfare HDU - 1540 F - Hotel G - 约会安排 HDU - 4553 区间合并
E - Tunnel Warfare HDU - 1540 对这个题目的思考:首先我们已经意识到这个是一个线段树,要利用线段树来解决问题,但是怎么解决呢,这个摧毁和重建的操作都很简单,但是这个查询怎么 ...
- POJ 4718 /// 树链剖分+线段树区间合并 求树上两点间的LCIS长度
题目大意: 给定n个点 每个点都有权值 接下来给定树的n条边 第 i 个数 a[i] 表示 i+1到a[i]之间 有一条边 给定q q个询问 每次询问给出 x y 求x到y的最长上升子序列的长度 题解 ...
- HDU 1540 区间合并线段树
题目大意: 就是给定一堆位置,进行删除还原,最后找到 t 位置上的最大连续位置 #include <cstdio> #include <cstring> #include &l ...
- HDU 3911 线段树区间合并、异或取反操作
题目:http://acm.hdu.edu.cn/showproblem.php?pid=3911 线段树区间合并的题目,解释一下代码中声明数组的作用: m1是区间内连续1的最长长度,m0是区间内连续 ...
- hdu 3911 Black And White (线段树 区间合并)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3911 题意: 给你一段01序列,有两个操作: 1.区间异或,2.询问区间最长的连续的1得长度 思路: ...
- HDU 3911 Black And White (线段树区间合并 + lazy标记)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3911 给你n个数0和1,m个操作: 0操作 输出l到r之间最长的连续1的个数 1操作 将l到r之间 ...
- hdu 1540 Tunnel Warfare 线段树 单点更新,查询区间长度,区间合并
Tunnel Warfare Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pi ...
- HDU 3308 线段树求区间最长连续上升子序列长度
题意:两种操作,Q L R查询L - R 的最长连续上升子序列长度,U pos val 单点修改值 #include <bits/stdc++.h> #define N 100005 us ...
随机推荐
- 进程间通信的两种实现方式(IPC)
进程间通信的两种实现方式(IPC) IPC: iter processing communicate 进程间通信:IPC(iter process communicate)linux free-m 可 ...
- hihocoder1079 离散化
思路:线段树 + 离散化. 测试用例: 3 10 1 10 1 3 6 10 实现: #include <bits/stdc++.h> using namespace std; typed ...
- 01认识Python和基础知识
1.了解Python Python的发展历史,作者Guido, 荷兰人 Python的优缺点 Python在网站的开发,如YouTube,科学计算,数据分析,在游戏后台开发等方面广泛使用 2.编写 ...
- 开启apahce的mod_speling.so模块,让使用apahce http服务器不再有大小写烦恼
今天把服务器重新安装系统,做apache调优前,优化下apache对网络地址大小写不区分的支持.记录如下: 编译mod_speling.so模块去除Apache-url大小写字母敏感的配置 1. 进入 ...
- java大文件读写操作,java nio 之MappedByteBuffer,高效文件/内存映射
java处理大文件,一般用BufferedReader,BufferedInputStream这类带缓冲的Io类,不过如果文件超大的话,更快的方式是采用MappedByteBuffer. Mapped ...
- [Windows Server 2012] 安装IIS8.5及FTP
★ 欢迎来到[护卫神·V课堂],网站地址:http://v.huweishen.com ★ 护卫神·V课堂 是护卫神旗下专业提供服务器教学视频的网站,每周更新视频. ★ 本节我们将带领大家:安装IIS ...
- mysql-mmm 部署高可用集群
集群的部署(mysql-mmm + 主从同步) 什么是集群? 多台服务器提供相同的服务 集群的好处? 节省成本. 配置集群? 准备环境:准备4台数据库服务器 准备服务器,能够ping 4 台数据库服务 ...
- liunx防火墙的基本操作
centos7中的使用 CentOS 7.0默认使用的是firewall作为防火墙 查看防火墙状态------->firewall-cmd --state 停止firewall-------&g ...
- 1+1/2+1/3+...+1/n为素数的证明
我们考虑不大于 n的最大的2 的幂 2^k. 令 有 其中 a/b是剩下的所有的项的和,由于乘以了最大的 2的幂,所以剩下的所有项的分母都是奇数,故而 b是奇数.如果 m是整数,那么就会导致等式右边的 ...
- slides 在线ppt && React && Angular
现在主流前端框架 有3个 Vue React Angular 如果有时间就都学习,理解一下他们的差异性~ 在线ppt的一个网站 这个是npm讲解的,不错 https://slides.com/seld ...