题目大意:

  有一个01序列,现在对于这个序列有五种变换操作和询问操作: 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。

思路:

  维护每一段数的和、左端和右端以及整段中连续的0和1的长度,并使用标记进行下传。

代码:

 #include<cstdio>
#include<cstring>
#include<iostream>
#define N 400000
using namespace std; int root,num,cnt,lmax[][N],rmax[][N],mmax[][N],sum[N],tag[][N],rev[N],h[N],t[N],rc[N],lc[N],a[N]; void up_date(int x,int k)
{
int l=lc[x],r=rc[x];
lmax[k][x]=lmax[k][l],rmax[k][x]=rmax[k][r];
if (lmax[k][l]==t[l]-h[l]+) lmax[k][x]+=lmax[k][r];
if (rmax[k][r]==t[r]-h[r]+) rmax[k][x]+=rmax[k][l];
mmax[k][x]=max(max(mmax[k][l],mmax[k][r]),rmax[k][l]+lmax[k][r]);
} void build(int l,int r,int &cur)
{
cur=++num,tag[][cur]=tag[][cur]=rev[cur]=;
h[cur]=l,t[cur]=r;
if (l==r)
{
lc[cur]=rc[cur]=;
lmax[][cur]=rmax[][cur]=mmax[][cur]=(a[l]==);
lmax[][cur]=rmax[][cur]=sum[cur]=mmax[][cur]=(a[r]==);
return;
}
int mid=l+r>>;
build(l,mid,lc[cur]),build(mid+,r,rc[cur]);
up_date(cur,),up_date(cur,),sum[cur]=sum[lc[cur]]+sum[rc[cur]];
} void mark(int x,int k)
{
tag[k][x]=,tag[k^][x]=rev[x]=,sum[x]=(t[x]-h[x]+)*k;
lmax[k][x]=rmax[k][x]=mmax[k][x]=t[x]-h[x]+;
lmax[k^][x]=rmax[k^][x]=mmax[k^][x]=;
} void re(int x)
{
rev[x]^=,sum[x]=t[x]-h[x]+-sum[x];
swap(lmax[][x],lmax[][x]),swap(rmax[][x],rmax[][x]),swap(mmax[][x],mmax[][x]);
} void push_down(int x)
{
if (tag[][x]) mark(lc[x],),mark(rc[x],),tag[][x]=;
if (tag[][x]) mark(lc[x],),mark(rc[x],),tag[][x]=;
if (rev[x]) re(lc[x]),re(rc[x]),rev[x]=;
} void change(int l,int r,int cur,int k)
{
if (h[cur]>r || t[cur]<l) return;
if (h[cur]>=l && t[cur]<=r)
{
if (k<) mark(cur,k);
else re(cur);
return;
}
push_down(cur);
change(l,r,lc[cur],k),change(l,r,rc[cur],k);
up_date(cur,),up_date(cur,),sum[cur]=sum[lc[cur]]+sum[rc[cur]];
} int ask1(int l,int r,int cur)
{
if (h[cur]>r || t[cur]<l) return ;
if (h[cur]>=l && t[cur]<=r) return sum[cur];
push_down(cur);
return ask1(l,r,lc[cur])+ask1(l,r,rc[cur]);
} int ask2(int l,int r,int cur)
{
if (l==h[cur] && r==t[cur]) return cur;
int mid=h[cur]+t[cur]>>;
push_down(cur);
if (r<=mid) return ask2(l,r,lc[cur]);
else if (l>mid) return ask2(l,r,rc[cur]);
else
{
int ans=++cnt;
lc[ans]=ask2(l,mid,lc[cur]),rc[ans]=ask2(mid+,r,rc[cur]);
up_date(ans,),up_date(ans,),sum[ans]=sum[lc[ans]]+sum[rc[ans]];
return ans;
}
} int main()
{
int n,m,i,x,y,z;
scanf("%d%d",&n,&m);
for (i=;i<=n;i++) scanf("%d",&a[i]);
build(,n,root);
for (i=;i<=m;i++)
{
scanf("%d%d%d",&z,&x,&y);
x++,y++;
if (z==) printf("%d\n",ask1(x,y,root));
else if (z==) cnt=num,printf("%d\n",mmax[][ask2(x,y,root)]);
else change(x,y,root,z);
}
return ;
}

最新文章

  1. 用Spire.doc来合并邮件
  2. 瀑布流布局——jquery
  3. 模拟jQuery简单封装ajax
  4. Java基础知识系列——日期
  5. Zabbix(二)--第一台主机监控及触发器
  6. linux下的shell运算(加、减、乘、除)
  7. 一个CentOS7的开发环境部署,包括防火墙|VPN|多IP多网关|HTTP代理服务器设置等
  8. Android内核开发:系统启动速度优化-Android OS启动优化(转)
  9. nyoj832 合并游戏(状态压缩DP)
  10. ARM学习日记
  11. 设计模式Template Method模式(Template Method)摘录
  12. LINUX 笔记-grep命令
  13. IO流(File类,IO流的分类,字节流和字符流,转换流,缓冲流,对象序列化)
  14. Spring知识点回顾(08)spring aware
  15. (light oj 1024) Eid (最小公倍数)
  16. python学习:注释、获取用户输入、字符串拼接、运算符、表达式
  17. [转]Prometheus 与 Grafana 实现服务器运行状态监控
  18. 需求:lr需要在一串数字中随机位置插入一个新数字的实现方式
  19. scrum学习笔记
  20. 客户端负载均衡Ribbon之二:Loadbalance的源码

热门文章

  1. Android Tab -- 使用ViewPager、PagerTitleStrip/PagerTabStrip来实现
  2. CSS学习笔记----CSS3自定义字体图标
  3. C#的初始化器
  4. 理解Java中的final和static关键字
  5. Dubbo应用与异常记录
  6. Linux 标准目录结构
  7. 在ubuntu上搭建开发环境10---英文版ubuntu安装中文输入法
  8. 【翻译十六】java-固定对象的定义方法
  9. 【翻译十二】java-并发之活性
  10. Win10 启动模拟器