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. C#方法拓展

    作用: “扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型.重新编译或以其他方式修改原始类型.” 要求: 1.拓展方法必须是在一个非嵌套.非泛型的静态类中定义.2.他至少有一个参数.3. ...

  2. js数据类型之判断

    js有几种类型,具体是:字符串(String).数字(Number).布尔(Boolean).数组(Array).对象(Object).空(Null).未定义(Undefined). js提供了typ ...

  3. 在linux中使用多个redis端口来构建redis集群

    大家好,这是我制作的redis集群搭建视频教程. 服务器:ubnutu server(版本18.10) redis:redis-4.0.12 我这里就简单说明下大概步骤了,详细请观看教学视频. 首先更 ...

  4. webform简单空间以及数据库访问

    1.简单控件 Label - 文字,编译后显示的是<span> 一说到边框:1.颜色 2.类型,比如solid实线3.width宽度Literal -里面可以承载很多东西,比如文字,比如a ...

  5. C#中this指针的用法示例

    这篇文章主要介绍了C#中this指针的用法,对初学者而言是非常重要的概念,必须加以熟练掌握,需要的朋友可以参考下. 本文实例展示了C#中this指针的用法,对于初学者进一步牢固掌握C#有很大帮助,具体 ...

  6. AJPFX关于java中可访问控制符和非访问控制符的详细总结

    1.类的修饰符分为:可访问控制符和非访问控制符两种. 可访问控制符是:公共类修饰符 public 非访问控制符有:抽象类修饰符 abstract :最终类修饰符 final 1 )公共类修饰符 pub ...

  7. BaseAtapter

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

  8. Android小玩意儿-- 从头开发一个正经的MusicPlayer(三)

    MusicService已经能够接收广播,通过广播接收的内容来做出相应的MediaPlayer对象的处理,包括播放,暂停,停止等,并当MediaPlayer对象的生命周期发生变化的时候,同样通过发送广 ...

  9. mac下安装nodejs

    下载 https://nodejs.org/en/ 安装 一步步继续就ok 验证 npm -v node -v Done!

  10. 我的关于phoneGap的安装及测试。

    一.PhoneGap简介 PhoneGap是一个用基于HTML,CSS和JavaScript的,创建移动跨平台移动应用程序的快速开发平台.它使开发者能够利用 iPhone,Android,Palm,S ...