//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 线段树 区间合并的更多相关文章

  1. POJ 3667 Hotel(线段树 区间合并)

    Hotel 转载自:http://www.cnblogs.com/scau20110726/archive/2013/05/07/3065418.html [题目链接]Hotel [题目类型]线段树 ...

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

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

  3. HDU 3911 Black And White(线段树区间合并+lazy操作)

    开始以为是水题,结果...... 给你一些只有两种颜色的石头,0为白色,1为黑色. 然后两个操作: 1 l r 将[ l , r ]内的颜色取反 0 l r 计算[ l , r ]内最长连续黑色石头的 ...

  4. poj3667 线段树 区间合并

    //Accepted 3728 KB 1079 ms //线段树 区间合并 #include <cstdio> #include <cstring> #include < ...

  5. hdu3911 线段树 区间合并

    //Accepted 3911 750MS 9872K //线段树 区间合并 #include <cstdio> #include <cstring> #include < ...

  6. 线段树(区间合并) POJ 3667 Hotel

    题目传送门 /* 题意:输入 1 a:询问是不是有连续长度为a的空房间,有的话住进最左边 输入 2 a b:将[a,a+b-1]的房间清空 线段树(区间合并):lsum[]统计从左端点起最长连续空房间 ...

  7. HDU 3308 LCIS (线段树区间合并)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308 题目很好懂,就是单点更新,然后求区间的最长上升子序列. 线段树区间合并问题,注意合并的条件是a[ ...

  8. SPOJ GSS1_Can you answer these queries I(线段树区间合并)

    SPOJ GSS1_Can you answer these queries I(线段树区间合并) 标签(空格分隔): 线段树区间合并 题目链接 GSS1 - Can you answer these ...

  9. 树链剖分——线段树区间合并bzoj染色

    线段树区间合并就挺麻烦了,再套个树链就更加鬼畜,不过除了代码量大就没什么其他的了.. 一些细节:线段树每个结点用结构体保存,pushup等合并函数改成返回一个结构体,这样好写一些 struct Seg ...

随机推荐

  1. Python语言及其应用 - 知识点遍历

    遍历python语法     2.基本元素:数字.字符串和变量 2.1 python有哪些基本类型? 布尔型(True, False),整型(42,100000),浮点型(3.14159,1.0e8) ...

  2. shell如何在指定文件的指定位置后面添加内容

    最近工作中遇到一个问题,想在某个文件的指定位置后面添加一个标志位,要求在shell脚本里实现. 问题说明: 想在sys_config.fex文本的某个字符串后面添加一个flag 例如:sys_conf ...

  3. 2016年Web前端面试题目汇总

    转载: 2016年Web前端面试题目汇总 以下是收集一些面试中经常会遇到的经典面试题以及自己面试过程中未解决的问题,通过对知识的整理以及经验的总结,重新巩固自身的前端基础知识,如有错误或更好的答案,欢 ...

  4. 3.5 EF Code First总结

    1. 主键约定 属性名为“ID”(不区分大小写)或类名的后面跟有“ID”. 2. 关系约定 模型之间的关系,EF根据针对类型定义的导航属性来推断关系. 3. 连接字符串约定 (1)默认配置 如果连接字 ...

  5. [HBuilder] 简介

    官网首页: http://www.dcloud.io/runtime.html 特点: 编码比其他工具快5倍 代码输入法:按下数字快速选择候选项 可编程代码块:一个代码块,少敲50个按键 内置emme ...

  6. [saiku] 通过 saiku 的 DEMO 分析 connection

    示例:FOODMART connection: foodmart catalog: FoodMart schema: FoodMart cube: Sales/HR/Sales 2/.../ ==== ...

  7. hdu----(1402)A * B Problem Plus(FFT模板)

    A * B Problem Plus Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other ...

  8. 【新手练习】类似Path的按钮,

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  9. 解析 MACH_O 文件

    现在做iOS开发的挺多,了解一下在苹果平台上程序运行的原理 解析 MACH_O 文件 这篇文章描述了如何解析 Mach-O 文件并稍微解释了一下它的格式.这不是一份权威指南,不过当你不知从何开始时,它 ...

  10. 读书笔记2:HTTP协议

    HTTP是什么 HTTP定义 HTTP( Hypertext Transfer Protocol, 超文本传输协议) 是在万维网上进行通信时所使用 的协议方案. HTTP的地位 了解HTTP协议的地位 ...