HYSBZ 1858 线段树 区间合并
//Accepted 14560 KB 1532 ms
//线段树 区间合并
/*
0 a b 把[a, b]区间内的所有数全变成0
1 a b 把[a, b]区间内的所有数全变成1
2 a b 把[a,b]区间内的所有数全部取反,也就是说把所有的0变成1,把所有的1变成0
3 a b 询问[a, b]区间内总共有多少个1
4 a b 询问[a, b]区间内最多有多少个连续的1
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <algorithm>
using namespace std;
/**
* This is a documentation comment block
* 如果有一天你坚持不下去了,就想想你为什么走到这儿!
* @authr songt
*/
;
struct node
{
int l,r;
int L1,R1; //左右连续1
int L0,R0; //左右连续0
int change; //-1 无操作 2取反,0全0 1全1
int sum1,sum0; //最大连续1,0
int all1,all0; //所有1,0
}f[imax_n*];
int a[imax_n];
int max(int a,int b)
{
return a>b?a:b;
}
int min(int a,int b)
{
return a<b?a:b;
}
int swap(int &a,int &b)
{
int t=a;
a=b;
b=t;
}
//由下向上合并
//f[t]的延迟标记是指延迟f[t]的两个孩子的操作,而f[t]已经完成该操作
void pushUp(int t)
{
//printf("pushUpt=%d\n",t);
*t].r-f[*t].l+;
*t+].r-f[*t+].l+;
f[t].L1=f[*t].L1;
*t].L1==lLen) f[t].L1+=f[*t+].L1;//左连续1的个数
f[t].R1=f[*t+].R1;
*t+].R1==rLen) f[t].R1+=f[*t].R1;//右连续1的个数
f[t].sum1=max(f[*t].sum1,f[*t+].sum1);
f[t].sum1=max(f[t].sum1,f[*t].R1+f[*t+].L1);//最大连续1=max(左边,右边,中间合并)
f[t].all1=f[*t].all1+f[*t+].all1; //所有1
f[t].L0=f[*t].L0;
*t].L0==lLen) f[t].L0+=f[*t+].L0;
f[t].R0=f[*t+].R0;
*t+].R0==rLen) f[t].R0+=f[*t].R0;
f[t].sum0=max(f[*t].sum0,f[*t+].sum0);
f[t].sum0=max(f[t].sum0,f[*t].R0+f[*t+].L0);
f[t].all0=f[*t].all0+f[*t+].all0;
}
void pushDown(int t)
{
)
{
//printf("pushDownt=%d\n",t);
*t].r-f[*t].l+;
*t+].r-f[*t+].l+;
) //set all 0
{
f[*t].change=f[*t+].change=;
f[t].change=-;
f[*t].L1=f[*t].R1=f[*t].sum1=f[*t].all1=;
f[*t].L0=f[*t].R0=f[*t].sum0=f[*t].all0=lLen;
f[*t+].L1=f[*t+].R1=f[*t+].sum1=f[*t+].all1=;
f[*t+].L0=f[*t+].R0=f[*t+].sum0=f[*t+].all0=rLen;
return ;
}
) //set all 1
{
f[*t].change=f[*t+].change=;
f[t].change=-;
f[*t].L1=f[*t].R1=f[*t].sum1=f[*t].all1=lLen;
f[*t].L0=f[*t].R0=f[*t].sum0=f[*t].all0=;
f[*t+].L1=f[*t+].R1=f[*t+].sum1=f[*t+].all1=rLen;
f[*t+].L0=f[*t+].R0=f[*t+].sum0=f[*t+].all0=;
return ;
}
) //0->1 1->0
{
f[t].change=-;
*t].change==-) //如果f[2*t]没有操作,则直接取反
{
f[*t].change=;
}
*t].change==) //如果f[2*t]已经标记为置0,取反后为置1
{
f[*t].change=;
}
*t].change==) //如果f[2*t]已经标记为置1,取反后为置0
{
f[*t].change=;
}
*t].change==) //如果f[2*t]已经取反,再次取反相当于没操作
{
f[*t].change=-;
}
swap(f[*t].L0,f[*t].L1); //f[2*t]进行取反操作,0,1的标记都要互换
swap(f[*t].R0,f[*t].R1);
swap(f[*t].sum0,f[*t].sum1);
swap(f[*t].all0,f[*t].all1);
//2*t+1 同 2*t
*t+].change==-)
{
f[*t+].change=;
}
*t+].change==)
{
f[*t+].change=;
}
*t+].change==)
{
f[*t+].change=;
}
*t+].change==)
{
f[*t+].change=-;
}
swap(f[*t+].L0,f[*t+].L1);
swap(f[*t+].R0,f[*t+].R1);
swap(f[*t+].sum0,f[*t+].sum1);
swap(f[*t+].all0,f[*t+].all1);
}
}
}
void build(int t,int l,int r)
{
f[t].l=l;
f[t].r=r;
f[t].change=-;
if (l==r)
{
f[t].L1=f[t].R1=f[t].sum1=f[t].all1=a[l];
f[t].L0=f[t].R0=f[t].sum0=f[t].all0=-a[l];
return ;
}
;
build(*t,l,mid);
build(*t+,mid+,r);
pushUp(t);
}
void update(int t,int l,int r,int op)
{
//printf("update l=%d r=%d\n",l,r);
if (f[t].l==l && f[t].r==r)
{
//如果是2号操作,需要考虑原来的操作
)
{
) f[t].change=;
) f[t].change=;
) f[t].change=;
) f[t].change=-;
}
else
{
//置0,1操作和原来的操作没关系
f[t].change=op;
}
) //该区间置0
{
f[t].L1=f[t].R1=f[t].sum1=f[t].all1=;
f[t].L0=f[t].R0=f[t].sum0=f[t].all0=f[t].r-f[t].l+;
}
) //该区间置1
{
f[t].L1=f[t].R1=f[t].sum1=f[t].all1=f[t].r-f[t].l+;
f[t].L0=f[t].R0=f[t].sum0=f[t].all0=;
}
) //该区间取反
{
swap(f[t].L0,f[t].L1);
swap(f[t].R0,f[t].R1);
swap(f[t].sum0,f[t].sum1);
swap(f[t].all0,f[t].all1);
}
return ;
}
pushDown(t); //如果操作的区间为当前区间的子区间,则要把当前区间的change传到子区间
;
*t,l,r,op);
else
{
*t+,l,r,op);
else
{
update(*t,l,mid,op);
update(*t+,mid+,r,op);
}
}
pushUp(t); //子区间修改完成后,要向父区间合并信息
}
//op==1 求所有1 op==0 求最大连续1
int query(int t,int l,int r,int op)
{
if (f[t].l==l && f[t].r==r)
{
) return f[t].all1;
return f[t].sum1;
}
pushDown(t);
;
*t,l,r,op);
else
{
*t+,l,r,op);
else
{
) *t,l,mid,op)+query(*t+,mid+,r,op);
int ans,ans1,ans2;
ans1=query(*t,l,mid,op);
ans2=query(*t+,mid+,r,op);
ans=max(ans1,ans2);
ans=max(ans,min(f[*t].R1,mid-l+)+min(f[*t+].L1,r-mid)); //r-mid=r-(mid+1)+1
return ans;
}
}
}
int n,Q;
int op,x,y;
void slove()
{
build(,,n);
;i<=Q;i++)
{
scanf("%d%d%d",&op,&x,&y);
x++;
y++;
)
{
update(,x,y,);
}
)
{
update(,x,y,);
}
)
{
update(,x,y,);
}
)
{
,x,y,);
printf("%d\n",t);
}
)
{
,x,y,);
printf("%d\n",t);
}
}
}
int main()
{
while (scanf("%d%d",&n,&Q)!=EOF)
{
;i<=n;i++)
scanf("%d",&a[i]);
slove();
}
;
}
HYSBZ 1858 线段树 区间合并的更多相关文章
- POJ 3667 Hotel(线段树 区间合并)
Hotel 转载自:http://www.cnblogs.com/scau20110726/archive/2013/05/07/3065418.html [题目链接]Hotel [题目类型]线段树 ...
- HDU 3911 线段树区间合并、异或取反操作
题目:http://acm.hdu.edu.cn/showproblem.php?pid=3911 线段树区间合并的题目,解释一下代码中声明数组的作用: m1是区间内连续1的最长长度,m0是区间内连续 ...
- HDU 3911 Black And White(线段树区间合并+lazy操作)
开始以为是水题,结果...... 给你一些只有两种颜色的石头,0为白色,1为黑色. 然后两个操作: 1 l r 将[ l , r ]内的颜色取反 0 l r 计算[ l , r ]内最长连续黑色石头的 ...
- poj3667 线段树 区间合并
//Accepted 3728 KB 1079 ms //线段树 区间合并 #include <cstdio> #include <cstring> #include < ...
- hdu3911 线段树 区间合并
//Accepted 3911 750MS 9872K //线段树 区间合并 #include <cstdio> #include <cstring> #include < ...
- 线段树(区间合并) POJ 3667 Hotel
题目传送门 /* 题意:输入 1 a:询问是不是有连续长度为a的空房间,有的话住进最左边 输入 2 a b:将[a,a+b-1]的房间清空 线段树(区间合并):lsum[]统计从左端点起最长连续空房间 ...
- HDU 3308 LCIS (线段树区间合并)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308 题目很好懂,就是单点更新,然后求区间的最长上升子序列. 线段树区间合并问题,注意合并的条件是a[ ...
- SPOJ GSS1_Can you answer these queries I(线段树区间合并)
SPOJ GSS1_Can you answer these queries I(线段树区间合并) 标签(空格分隔): 线段树区间合并 题目链接 GSS1 - Can you answer these ...
- 树链剖分——线段树区间合并bzoj染色
线段树区间合并就挺麻烦了,再套个树链就更加鬼畜,不过除了代码量大就没什么其他的了.. 一些细节:线段树每个结点用结构体保存,pushup等合并函数改成返回一个结构体,这样好写一些 struct Seg ...
随机推荐
- mysql+tomcat+spring 配置心得(从0开始搭环境)
前几天公司竞一个标要做个POC,前端AugularJs做mobile界面,后端Spring MVC做Restful API供前端调用. 时间紧急,大家都忙,so我这个不写代码的闲人花一上午配了一套Sp ...
- iOS 控制单个控制器旋转
iOS 控制单个控制器旋转 控制单个ViewController 的旋转 //不旋转,保持竖屏 //iOS 5 - (BOOL) shouldAutorotateToInterfaceOrientat ...
- Shader中贴图知识汇总: 漫反射贴图、凹凸贴图、高光贴图、 AO贴图、环境贴图、 光照纹理及细节贴图
原文过于冗余,精读后做了部分简化与测试实践,原文地址:http://www.j2megame.com/html/xwzx/ty/2571.html http://www.cnblogs.com/z ...
- 中医与DBA
很多药方,只要吃不死,总有一款适合你.哈哈.我要做西医,先检查身体,再了解每种药的作用,做到对症下药.
- 关于MySQL回滚机制
在事务中,每个正确的原子操作都会被顺序执行,直到遇到错误的原子操作,此时事务会将之前的操作进行回滚.回滚的意思是如果之前是插入操作,那么会执行删 除插入的记录,如果之前是update操作,也会执行up ...
- hdu 1021
刚开始直接按题意来写,WA了,唉,果然经验不够..然后开始找规律,本来一看到这种题,第一反应就是规律题,然后看看题意,貌似没啥规律哦!就像当时学DP一样,总是想当然被智商压制了啊喂! #include ...
- Innodb中的事务隔离级别和锁的关系
前言: 我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁这种方式.同时数据库又是个高并发的应用,同一时间会有大量的并发访问,如果加锁过度,会极大的降低并发处理能力. ...
- jquery 设置css样式
$("#61dh a").css('color', 多个样式属性 var divcss = { background: '#EEE', width: '478px', mar ...
- postgresql 触发器
一.创建事件触发器 1.ddl_command_start - 一个DDL开始执行前被触发: 2.ddl_command_end - 一个DLL 执行完成后被触发: 3.sql_drop -- 删除一 ...
- from __future__ import absolute_import
from __future__ import absolute_import 这样以后:局部的包将不能覆盖全局的包, 本地的包必须使用相对引用了. 例: from celery import Cele ...