考虑需要资瓷哪些操作:区间赋值为0;统计区间1的个数;将区间前k个0变为1;询问区间最长全0子串。于是线段树维护区间1的个数、0的个数、最长前缀后缀全0子串即可。稍微困难的是用一个log实现将区间前k个0变为1,线段树上二分尽量往左边改即可,可以令修改函数返回值为剩余能改的1的个数。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 200010
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')) c=getchar();return c;}
int gcd(int n,int m){return m==?n:gcd(m,n%m);}
int n,m,L[N<<],R[N<<];
struct data{int sum0,sum1,pre,suf,len,lazy;
}tree[N<<];
void update(int k,int x)
{
if (x==)
{
tree[k].sum0=tree[k].pre=tree[k].suf=tree[k].len=R[k]-L[k]+;
tree[k].sum1=;
}
else
{
tree[k].sum0=tree[k].pre=tree[k].suf=tree[k].len=;
tree[k].sum1=R[k]-L[k]+;
}
tree[k].lazy=x;
}
void up(int k)
{
tree[k].sum0=tree[k<<].sum0+tree[k<<|].sum0;
tree[k].sum1=tree[k<<].sum1+tree[k<<|].sum1;
if (tree[k<<].pre==R[k<<]-L[k<<]+) tree[k].pre=tree[k<<].pre+tree[k<<|].pre;
else tree[k].pre=tree[k<<].pre;
if (tree[k<<|].suf==R[k<<|]-L[k<<|]+) tree[k].suf=tree[k<<|].suf+tree[k<<].suf;
else tree[k].suf=tree[k<<|].suf;
tree[k].len=max(max(tree[k<<].len,tree[k<<|].len),tree[k<<].suf+tree[k<<|].pre);
}
void down(int k)
{
update(k<<,tree[k].lazy);
update(k<<|,tree[k].lazy);
tree[k].lazy=-;
}
void build(int k,int l,int r)
{
L[k]=l,R[k]=r;tree[k].lazy=-;
if (l==r) {tree[k].sum1=;return;}
int mid=l+r>>;
build(k<<,l,mid);
build(k<<|,mid+,r);
up(k);
}
void modify(int k,int l,int r)
{
if (L[k]==l&&R[k]==r) {update(k,);return;}
if (~tree[k].lazy) down(k);
int mid=L[k]+R[k]>>;
if (r<=mid) modify(k<<,l,r);
else if (l>mid) modify(k<<|,l,r);
else modify(k<<,l,mid),modify(k<<|,mid+,r);
up(k);
}
int calc(int k,int l,int r)
{
if (L[k]==l&&R[k]==r) return tree[k].sum1;
if (~tree[k].lazy) down(k);
int mid=L[k]+R[k]>>;
if (r<=mid) return calc(k<<,l,r);
else if (l>mid) return calc(k<<|,l,r);
else return calc(k<<,l,mid)+calc(k<<|,mid+,r);
}
int query(int k,int l,int r)
{
if (L[k]==l&&R[k]==r) return tree[k].len;
if (~tree[k].lazy) down(k);
int mid=L[k]+R[k]>>;
if (r<=mid) return query(k<<,l,r);
else if (l>mid) return query(k<<|,l,r);
else return max(max(query(k<<,l,mid),query(k<<|,mid+,r)),min(tree[k<<].suf,mid-l+)+min(tree[k<<|].pre,r-mid));
}
int paint(int k,int l,int r,int x)
{
if (!x) return ;
if (L[k]==l&&R[k]==r&&x>=tree[k].sum0) {x-=tree[k].sum0;update(k,);return x;}
if (~tree[k].lazy) down(k);
int mid=L[k]+R[k]>>;
if (r<=mid) x=paint(k<<,l,r,x);
else if (l>mid) x=paint(k<<|,l,r,x);
else
{
int t=paint(k<<,l,mid,x);
if (t>=) x=paint(k<<|,mid+,r,t);
else x=;
}
up(k);
return x;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj4592.in","r",stdin);
freopen("bzoj4592.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read(),m=read();
build(,,n);
while (m--)
{
int op=read(),l=read(),r=read();
if (op==) modify(,l,r);
else if (op==)
{
int x=read(),y=read();
int k=calc(,l,r);
modify(,l,r);
paint(,x,y,k);
}
else printf("%d\n",query(,l,r));
}
return ;
}

最新文章

  1. AFNetworking图片上传
  2. 模板类 error LNK2019: 无法解析的外部符号
  3. commitizen-规范commit-message
  4. [转]C++中四种类型转换符的总结
  5. GET请求中URL的最大长度限制总结
  6. css大牛的博客
  7. Hadoop 的子项目
  8. web跳转到自己的app
  9. eclipse插件maven的使用,web打包成WAR,tomcat下直接运行
  10. .NET Core项目从xproj+project.json向csproj迁移简介
  11. 使用OracleDBLink进行数据库之间对象的访问操作
  12. JQuery源码-------JQuery中数值型变量的判断isNumeric
  13. git学习四:eclipse使用git提交项目
  14. gradle 修改生成的apk的名字
  15. Django中web开发用md5加密图片名并存储静态文件夹
  16. Python标准库--time模块的详解
  17. 算法之Python实现 - 001 : 换钱的最少货币数
  18. jQuery实现鼠标点击div外的地方div隐藏消失的效果(转)
  19. windwos下基于exp的提权
  20. Dapper的数据库连接管理(打开、关闭)

热门文章

  1. 【php练习源码】
  2. java初级应用:环境安装及配置
  3. 5.Python的语言特点
  4. 渗透测试实验(i春秋 真的很简单)
  5. Linux命令备忘录: jobs 显示Linux中的任务列表及任务状态命令
  6. linux io 学习笔记(03)---共享内存,信号灯,消息队列
  7. ASP.NET MVC文件上传【转】
  8. C#窗口抖动
  9. 新手入门Sqlalchemy
  10. 基于jersey和Apache Tomcat构建Restful Web服务(一)