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 区间合并求最大长度的问题的更多相关文章

  1. Tunnel Warfare HDU 1540 区间合并+最大最小值

    Tunnel Warfare HDU 1540 区间合并+最大最小值 题意 D x是破坏这个点,Q x是表示查询以x所在的最长的连续的点的个数,R是恢复上一次破坏的点. 题解思路 参考的大佬博客 这里 ...

  2. E - Tunnel Warfare HDU - 1540 F - Hotel G - 约会安排 HDU - 4553 区间合并

    E - Tunnel Warfare HDU - 1540 对这个题目的思考:首先我们已经意识到这个是一个线段树,要利用线段树来解决问题,但是怎么解决呢,这个摧毁和重建的操作都很简单,但是这个查询怎么 ...

  3. POJ 4718 /// 树链剖分+线段树区间合并 求树上两点间的LCIS长度

    题目大意: 给定n个点 每个点都有权值 接下来给定树的n条边 第 i 个数 a[i] 表示 i+1到a[i]之间 有一条边 给定q q个询问 每次询问给出 x y 求x到y的最长上升子序列的长度 题解 ...

  4. HDU 1540 区间合并线段树

    题目大意: 就是给定一堆位置,进行删除还原,最后找到 t 位置上的最大连续位置 #include <cstdio> #include <cstring> #include &l ...

  5. HDU 3911 线段树区间合并、异或取反操作

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=3911 线段树区间合并的题目,解释一下代码中声明数组的作用: m1是区间内连续1的最长长度,m0是区间内连续 ...

  6. hdu 3911 Black And White (线段树 区间合并)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3911 题意: 给你一段01序列,有两个操作: 1.区间异或,2.询问区间最长的连续的1得长度 思路: ...

  7. 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之间 ...

  8. hdu 1540 Tunnel Warfare 线段树 单点更新,查询区间长度,区间合并

    Tunnel Warfare Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pi ...

  9. HDU 3308 线段树求区间最长连续上升子序列长度

    题意:两种操作,Q L R查询L - R 的最长连续上升子序列长度,U pos val 单点修改值 #include <bits/stdc++.h> #define N 100005 us ...

随机推荐

  1. 启动hadoop时报root@localhost's password: localhost: Permission denied, please try again.错误。

    背景:在装完hadoop及jdk之后,在执行start-all.sh的时候出现root@localhost's password:localhost:permission denied,please ...

  2. iOS中使用 Reachability 检测网络区分手机网络类型 WiFi 和2 3 4 G

    如果你想在iOS程序中提供一仅在wifi网络下使用(Reeder),或者在没有网络状态下提供离线模式(Evernote).那么你会使用到Reachability来实现网络检测. 写本文的目的 了解Re ...

  3. BaseAtapter

    本文用于实现一个通用的BaseAdapter类,统一产品的Adapter类,作为一个工具类,减少重复性工作,增加开发效率. 序 我们在开发项目的过程中,经常会用到ListView.GridView这一 ...

  4. ICEcoder显示汉字出现乱码的处理

    在网上看到icecoder这个小东西,是一个基于web的编辑器,很不错.唯一的缺点是打开的文件中汉字会变成乱码. 经查看源代码,在lib/file-control.php中,第89行是: echo ' ...

  5. ES5函数新增的方法(call、apply、bind)

    1.call()的使用<script type="text/javascript"> var obj1 = { name:'bob', fn:function(){ c ...

  6. ios水果风暴游戏源码项目下载

    这是一款ios水果风暴游戏源码下载,介绍给大家一下,喜欢的朋友可以下载学习一下吧.应用介绍:这是一个以获得高分和挑战更高难度为目的的游戏.游戏中有九种不同的卡通水果,您可以交换屏幕中两个相邻水果的位置 ...

  7. win7系统 windows update 总是更新失败解决方法:

    win7系统 windows update 总是更新失败解决方法: 右键单击桌面“计算机”选择“管理“. 进到“计算机管理“窗口后,展开”服务和应用程序“并双击”服务“,在窗口右侧按照名称找到”Win ...

  8. PHP CLI应用的调试原理

    我们在Eclipse里选中一个PHP文件,右键选择Debug As->PHP CLI Application. 所谓CLI应用,是指这种脚本文件不需要任何Web服务器即可运行,当然, PHP运行 ...

  9. pip install python-igraph 报错,C core of igraph 没有安装。

    (一)问题描述 Centos7 安装python-igraph时,pip install python-igraph 报错,C core of igraph 没有安装. failure: repoda ...

  10. 【整理】解决vue不相关组件之间的数据传递----vuex的学习笔记,解决报错this.$store.commit is not a function

    解决vue不相关组件之间的数据传递----vuex的学习笔记,解决报错this.$store.commit is not a function https://www.cnblogs.com/jaso ...