题目链接:点击查看

题目大意:给定一个初始的数列,然后依次进行m次操作:

  1. 0 a b:将闭区间[a,b]内的点都变为0
  2. 1 a b:将闭区间[a,b]内的点都变为1
  3. 2 a b:将闭区间[a,b]内的点1变为0,0变为1(相当于取异或)
  4. 3 a b:查询闭区间[a,b]内有多少个1
  5. 4 a b:查询闭区间[a,b]内的最大连续的1的长度

题目分析:操作1、2、4是最简单的线段树操作,区间更新,区间查询,操作3、5是进阶一点的线段树操作,即区间合并,这两类操作分着做就十分简单了,写上模板只要不出错就没问题,但是如果这两类问题结合到一起,就要考虑lazy标记的次序问题了,这就涉及到这两个lazy标记之间的关系了,为了方便讲解,区间和覆盖的lazy标记下面我就称为lazy,取异或的lazy标记下面我称为xor:

首先,覆盖lazy的优先级要大于异或xor,如果该区间被覆盖了,那么他之前的异或标记xor将清零,如果之前不管经过了多少操作,只要本次操作是覆盖,那么之前的所有操作都可以视为无效。

相对的,如果之前都是覆盖操作,而本次操作是异或,则子区间段接下来都需要异或处理才行。

综上所述,lazy的优先级大于xor,更新lazy的同时记得清空xor,下传lazy的同时记得清空子区间的xor,更新和下传xor的时候不影响lazy,这样实现每一个步骤就能实现这个题目了,一定一定要注意细节,也要同时注意一下封装,因为封装起来肯定用起来比较方便,而手写很容易不小心写错,调试的时候就难受了,上代码了:

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<cmath>
#include<set>
#include<sstream>
#define ls (k<<1)
#define rs (k<<1|1)
using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=1e5+100;struct Node
{int l,r;int lazy,x_or;int l1,r1,all1;int l0,r0,all0;int sum1;int cal_len(){return r-l+1;}int mid(){return l+r>>1;}
}tree[N<<2];void pushup(int k)
{tree[k].sum1=tree[ls].sum1+tree[rs].sum1;tree[k].l0=tree[ls].l0;tree[k].r0=tree[rs].r0;if(tree[k].l0==tree[ls].cal_len())tree[k].l0+=tree[rs].l0;if(tree[k].r0==tree[rs].cal_len())tree[k].r0+=tree[ls].r0;tree[k].all0=max(max(tree[ls].all0,tree[rs].all0),tree[ls].r0+tree[rs].l0);tree[k].l1=tree[ls].l1;tree[k].r1=tree[rs].r1;if(tree[k].l1==tree[ls].cal_len())tree[k].l1+=tree[rs].l1;if(tree[k].r1==tree[rs].cal_len())tree[k].r1+=tree[ls].r1;tree[k].all1=max(max(tree[ls].all1,tree[rs].all1),tree[ls].r1+tree[rs].l1);
}void XOR(int k)
{swap(tree[k].l1,tree[k].l0);swap(tree[k].r1,tree[k].r0);swap(tree[k].all1,tree[k].all0);tree[k].sum1=tree[k].cal_len()-tree[k].sum1;
}void pushdown(int k)
{if(tree[k].lazy!=-1){tree[ls].lazy=tree[rs].lazy=tree[k].lazy;tree[ls].x_or=tree[rs].x_or=0;if(tree[k].lazy){tree[ls].l0=tree[ls].r0=tree[ls].all0=0;tree[rs].l0=tree[rs].r0=tree[rs].all0=0;tree[ls].sum1=tree[ls].cal_len();tree[rs].sum1=tree[rs].cal_len();tree[ls].l1=tree[ls].r1=tree[ls].all1=tree[ls].cal_len();tree[rs].l1=tree[rs].r1=tree[rs].all1=tree[rs].cal_len();}else{tree[ls].l0=tree[ls].r0=tree[ls].all0=tree[ls].cal_len();tree[rs].l0=tree[rs].r0=tree[rs].all0=tree[rs].cal_len();tree[ls].sum1=0;tree[rs].sum1=0;tree[ls].l1=tree[ls].r1=tree[ls].all1=0;tree[rs].l1=tree[rs].r1=tree[rs].all1=0;}tree[k].lazy=-1;}if(tree[k].x_or){tree[ls].x_or^=1;tree[rs].x_or^=1;tree[k].x_or=0;XOR(ls);XOR(rs);}
}void build(int k,int l,int r)
{tree[k].l=l;tree[k].r=r;tree[k].lazy=-1;tree[k].x_or=0;if(l==r){int num;scanf("%d",&num);tree[k].l1=tree[k].r1=tree[k].all1=tree[k].sum1=num;tree[k].l0=tree[k].r0=tree[k].all0=num^1;return;}int mid=tree[k].mid();build(ls,l,mid);build(rs,mid+1,r);pushup(k);
}void update1(int k,int l,int r,int val)
{if(tree[k].r<l||tree[k].l>r)return;if(tree[k].l>=l&&tree[k].r<=r){tree[k].lazy=val;tree[k].x_or=0;if(val){tree[k].l0=tree[k].r0=tree[k].all0=0;tree[k].sum1=tree[k].cal_len();tree[k].l1=tree[k].r1=tree[k].all1=tree[k].cal_len();}else{tree[k].l0=tree[k].r0=tree[k].all0=tree[k].cal_len();tree[k].sum1=0;tree[k].l1=tree[k].r1=tree[k].all1=0;}return;}pushdown(k);update1(ls,l,r,val);update1(rs,l,r,val);pushup(k);
}void update2(int k,int l,int r)
{if(tree[k].r<l||tree[k].l>r)return;if(tree[k].l>=l&&tree[k].r<=r){tree[k].x_or^=1;XOR(k);return;}pushdown(k);update2(ls,l,r);update2(rs,l,r);pushup(k);
}int query1(int k,int l,int r)
{if(tree[k].r<l||tree[k].l>r)return 0;if(tree[k].l>=l&&tree[k].r<=r){return tree[k].sum1;}pushdown(k);return query1(ls,l,r)+query1(rs,l,r);
}Node query2(int k,int l,int r)
{if(tree[k].l>=l&&tree[k].r<=r){return tree[k];}pushdown(k);int mid=tree[k].mid();if(mid>=r)return query2(ls,l,r);else if(mid<l)return query2(rs,l,r);else{Node ans1,ans2,ans;ans1=query2(ls,l,r);ans2=query2(rs,l,r);ans.l1=ans1.l1;ans.r1=ans2.r1;if(ans.l1==ans1.r-ans1.l+1)ans.l1+=ans2.l1;if(ans.r1==ans2.r-ans2.l+1)ans.r1+=ans1.r1;ans.all1=max(max(ans1.all1,ans2.all1),ans1.r1+ans2.l1);return ans;}
}void query(int k)
{if(tree[k].l==tree[k].r){printf("%d ",tree[k].sum1);return;}pushdown(k);query(ls);query(rs);
}int main()
{
//  freopen("input.txt","r",stdin);int w;cin>>w;while(w--){int n,m;scanf("%d%d",&n,&m);build(1,1,n);while(m--){int op,x,y;scanf("%d%d%d",&op,&x,&y);x++;y++;if(op==0){update1(1,x,y,0);}else if(op==1){update1(1,x,y,1);}else if(op==2){update2(1,x,y);}else if(op==3){printf("%d\n",query1(1,x,y));}else if(op==4){printf("%d\n",query2(1,x,y).all1);}}}return 0;
}

HDU - 3397 Sequence operation(线段树+区间合并)相关推荐

  1. hdu 3397 Sequence operation(线段树,lazy,区间合并)

    hdu 3397 Sequence operation 线段树lazy和区间合并结合的一个题,相当于几个题集中到一起嘛,分开想就好了 0,1,2操作都要lazy,2的异或操作找到每一只含1或只含0的区 ...

  2. HDU 3397 Sequence operation 线段树 成段更新 区间合并

    比较综合的题. 两个标记  setv,xorr.setv的优先级高于xorr,当一个节点获得一个setv时,他之前的xorr要清除. //#pragma comment(linker, "/ ...

  3. HDU - 2871 Memory Control(线段树+区间合并)好题!

    题目链接:点击查看 题目大意:给定n个内存和m个操作,分别是: New x:从内存编号1开始向右查找,分配一个长度为x的空间,若找到输出区间的首地址,否则输出Reject New: Free x:释放 ...

  4. HDU - 1540 Tunnel Warfare(线段树+区间合并)

    题目链接:点击查看 题目大意:给定n个村庄,初始化全部连接为一条直线,需要依次执行m个操作,D表示摧毁第i个村庄的连接,R表示恢复最后一 个被摧毁的村庄的连接,Q表示询问包括本身在内,与第i个村庄相连 ...

  5. HDU 1540 Tunnel Warfare 线段树区间合并

    Tunnel Warfare 题意:D代表破坏村庄,R代表修复最后被破坏的那个村庄,Q代表询问包括x在内的最大连续区间是多少 思路:一个节点的最大连续区间由(左儿子的最大的连续区间,右儿子的最大连续区 ...

  6. hdu 1540 Tunnel Warfare(线段树区间合并)

    hdu 1540 Tunnel Warfare 记录每个节点的最大左连续值.最大右连续值.最大连续值,向上更新的是常规的区间合并处理方式 关键是想到如何去查询,如果查询节点落在左儿子节点的右连续段中, ...

  7. HDU 3397 Sequence operation(线段树)

    HDU 3397 Sequence operation 题目链接 题意:给定一个01序列,有5种操作 0 a b [a.b]区间置为0 1 a b [a,b]区间置为1 2 a b [a,b]区间0变 ...

  8. Tunnel Warfare(HDU1540+线段树+区间合并)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1540 题目: 题意:总共有n个村庄,有q次操作,每次操作分为摧毁一座村庄,修复一座村庄,和查询与询问的 ...

  9. HDU3308 线段树区间合并

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308 ,简单的线段树区间合并. 线段树的区间合并:一般是要求求最长连续区间,在PushUp()函数中实 ...

最新文章

  1. CentOS 7.3 安装MySQL--Java--Tomcat
  2. 转载:如何快速转载CSDN及博客园中的博客
  3. java中什么是类型_什么是Java中基本数据类型?
  4. springboot-文件上传xls及POI操作Excel
  5. .NET中颜色的转换方法总结
  6. Mysql 多实例multi_mysqld_multi多实例运行
  7. okta使用_使用Okta的单点登录保护您的Vert.x服务器
  8. matlab打开笔记本摄像头_如何解决笔记本电脑摄像头异常问题
  9. php ab压力测试,安装Xcache缓存加速php及ab压力测试结果
  10. 2015.8.3 Java
  11. SWPUACM第二次周赛
  12. 优先经验回放(Prioritized Experience Replay)
  13. matlab2016a下载包及安装教程
  14. 抖音新带货王诞生了:老把头和老解
  15. opencv第九天pro
  16. wpf listview透明但字不要透明_早春松树松针上出现透明液体,不要不在意,可能是松大蚜在危害...
  17. java后端开发面经(一)
  18. 如何写好Change Log(Commit Log)---分享
  19. maven 打包跳过单元测试
  20. c语言程序结构设计的心得,写给新手 选择结构程序设计总结

热门文章

  1. Nginx静态资源优化配置之tcp_nopush和tcp_nodelay
  2. 基于注册中心的Dubbo服务
  3. 密码登录模式流程分析
  4. SpringMVC概述
  5. flume高可用-failover-模型分析
  6. HDFS的namenode和datanode
  7. SpringBoot_web开发-webjars静态资源映射规则
  8. plsql(轻量版)_异常处理机制
  9. java imap 标记已读,JavaMail通过IMAP和POP3接收未读以及设置已读邮件
  10. php paypal订单号查询,php – 在交易后从PayPal获取信息