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 ...
随机推荐
- Sql Server中通配符的使用
Sql Server中通配符的使用 通配符_ "_"号表示任意单个字符,该符号只能匹配一个字符."_"可以放在查询条件的任意位置,且只能代表一个字符.一个汉字只 ...
- 【转】 Linux下的多线程编程
作者:gnuhpc 出处:http://www.cnblogs.com/gnuhpc/原文链接:http://www.cnblogs.com/gnuhpc/archive/2012/12/07/280 ...
- redis.conf详解
# Redis示例配置文件 # 注意单位问题:当需要设置内存大小的时候,可以使用类似1k.5GB.4M这样的常见格式: # # 1k => bytes # 1kb => bytes # 1 ...
- C#中操作txt,抛出“正由另一进程使用,因此该进程无法访问此文件”
将你的File.Create(fileName); //创建fileName路径的文本改为 1 2 3 using (FileStream fs = File.Create(fileName)){} ...
- python3.x随手笔记1
语法分析 Python程序读取的 解析器 . 解析器的输入流 令牌 ,生成的 词法分析程序 . 这一章描述了如何 词法分析程序把一个文件分解成令牌. Python读取程序文本作为Unicode代码点; ...
- json小例子
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8 ...
- CSS3 Media Queries
Media Queries直译过来就是“媒体查询”,在我们平时的Web页面中head部分常看到这样的一段代码: <link href="css/reset.css" rel= ...
- YanYan Self Introduction
My Website: http://finehappy.com/
- Tomcat性能调优-让小猫飞奔[转]
http://blog.csdn.net/lifetragedy/article/details/7708724 http://blog.csdn.net/lifetragedy/articl ...
- .NET开发知识体系
记得几年前写过一篇关于.NET开发方面的知识总结,但是随着技术的发展以及自己技术理解的提升,觉得有必要对那篇文章加以更新和完善. 最近在园子里也看到有人写关于.NET知识体系的文章,特别是灵感之源写的 ...