博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【BZOJ4592】[Shoi2015]脑洞治疗仪 线段树
阅读量:4685 次
发布时间:2019-06-09

本文共 3240 字,大约阅读时间需要 10 分钟。

【BZOJ4592】[Shoi2015]脑洞治疗仪

Description

曾经发明了自动刷题机的发明家SHTSC又公开了他的新发明:脑洞治疗仪--一种可以治疗他因为发明而日益增大的脑洞的神秘装置。
为了简单起见,我们将大脑视作一个01序列。1代表这个位置的脑组织正常工作,0代表这是一块脑洞。
1
0 1 0 0 0 1 1 1 0
脑洞治疗仪修补某一块脑洞的基本工作原理就是将另一块连续区域挖出,将其中正常工作的脑组织填补在这块脑洞中。
(所以脑洞治疗仪是脑洞的治疗仪?)
例如,用上面第8号位置到第10号位置去修补第1号位置到第4号位置的脑洞。我们就会得到:
1
1 1 1 0 0 1 0 0 0
如果再用第1号位置到第4号位置去修补第8号位置到第10号位置:
0
0 0 0 0 0 1 1 1 1
这是因为脑洞治疗仪会把多余出来的脑组织直接扔掉。
如果再用第7号位置到第10号位置去填补第1号位置到第6号位置:
1
1 1 1 0 0 0 0 0 0
这是因为如果新脑洞挖出来的脑组织不够多,脑洞治疗仪仅会尽量填补位置比较靠前的脑洞。
假定初始时SHTSC并没有脑洞,给出一些挖脑洞和脑洞治疗的操作序列,你需要即时回答SHTSC的问题:
在大脑某个区间中最大的连续脑洞区域有多大。

Input

第一行两个整数n,m。表示SHTSC的大脑可分为从1到n编号的n个连续区域。有m个操作。
以下m行每行是下列三种格式之一。
0 l r :SHTSC挖了一个从l到r的脑洞。
1 l0 r0 l1 r2 :SHTSC进行了一次脑洞治疗,用从l0到r0的脑组织修补l1到r1的脑洞。
2 l r :SHTSC询问l到r这段区间最大的脑洞有多大。
n,m <=200000,1<=l<=r<=n

Output

对于每个询问,输出一行一个整数,表示询问区间内最大连续脑洞区域有多大。

Sample Input

10 10
0 2 2
0 4 6
0 10 10
2 1 10
1 8 10 1 4
2 1 10
1 1 4 8 10
2 1 10
1 7 10 1 6
2 1 10

Sample Output

3
3
6
6

题解:直接用线段树模拟就行,这里只说1操作。

先统计原位置有多少个have,再将原位置清空。如果能将目标位置填满,直接填满即可。否则我们需要找到应该填到哪里,即第have个空位的位置。这个可以在线段树上二分实现。

 

#include 
#include
#include
#define lson x<<1#define rson x<<1|1using namespace std;const int maxn=200010;int n,m;struct node{ int sum,tag,ls,rs,sm; node () {sum=ls=rs=sm=0,tag=-1;} node operator + (const node &b) const { node c; c.sum=sum+b.sum; if(sum&&sum==ls&&sum==rs) c.ls=sum+b.ls; else c.ls=ls; if(b.sum&&b.sum==b.ls&&b.sum==b.rs) c.rs=rs+b.sum; else c.rs=b.rs; c.sm=max(max(sm,b.sm),rs+b.ls); return c; }}s[maxn<<2];inline int rd(){ int ret=0,f=1; char gc=getchar(); while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();} while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar(); return ret*f;}inline void cover(int l,int r,int x,int v){ if(v) s[x].tag=1,s[x].sum=s[x].ls=s[x].rs=s[x].sm=r-l+1; else s[x].tag=s[x].sum=s[x].ls=s[x].rs=s[x].sm=0;}inline void pushdown(int l,int r,int x){ if(s[x].tag!=-1) { int mid=(l+r)>>1; cover(l,mid,lson,s[x].tag),cover(mid+1,r,rson,s[x].tag),s[x].tag=-1; }}void updata(int l,int r,int x,int a,int b,int c){ if(a>b) return ; if(a<=l&&r<=b) { cover(l,r,x,c); return ; } pushdown(l,r,x); int mid=(l+r)>>1; if(a<=mid) updata(l,mid,lson,a,b,c); if(b>mid) updata(mid+1,r,rson,a,b,c); s[x]=s[lson]+s[rson];}node query(int l,int r,int x,int a,int b){ if(a>b) return node(); if(a<=l&&r<=b) return s[x]; pushdown(l,r,x); int mid=(l+r)>>1; if(b<=mid) return query(l,mid,lson,a,b); if(a>mid) return query(mid+1,r,rson,a,b); return query(l,mid,lson,a,b)+query(mid+1,r,rson,a,b);}int find(int l,int r,int x,int a){ if(!a) return 0; if(l==r) return l; pushdown(l,r,x); int mid=(l+r)>>1; if(s[lson].sum>=a) return find(l,mid,lson,a); return find(mid+1,r,rson,a-s[lson].sum);}int main(){ int i,a,b,c,d,op,hav,ned; n=rd(),m=rd(); for(i=1;i<=m;i++) { op=rd(),a=rd(),b=rd(); if(op==0) updata(1,n,1,a,b,1); if(op==1) { c=rd(),d=rd(); hav=b-a+1-query(1,n,1,a,b).sum; updata(1,n,1,a,b,1); ned=query(1,n,1,c,d).sum; if(hav>=ned) updata(1,n,1,c,d,0); else updata(1,n,1,c,find(1,n,1,query(1,n,1,1,c-1).sum+hav),0); } if(op==2) printf("%d\n",query(1,n,1,a,b).sm); } return 0;}//10 10 0 2 2 0 4 6 0 10 10 2 1 10 1 8 10 1 4 2 1 10 1 1 4 8 10 2 1 10 1 7 10 1 6 2 1 10

 

转载于:https://www.cnblogs.com/CQzhangyu/p/7670303.html

你可能感兴趣的文章
android wear开发之:增加可穿戴设备功能到通知中 - Adding Wearable Features to Notifications...
查看>>
压缩文件函数库(转载)
查看>>
【转】ubuntu12.04没有/var/log/messages解决
查看>>
Oracle EBS 初始化用户密码
查看>>
SYS_CONTEXT 详细用法
查看>>
Pycharm配置autopep8让Python代码更符合pep8规范
查看>>
函数的复写
查看>>
17_重入锁ReentrantLock
查看>>
winform窗口关闭提示
查看>>
64款工具,总有合适您的那款
查看>>
我的第一篇博客
查看>>
大数据学习线路整理
查看>>
【C++算法与数据结构学习笔记------单链表实现多项式】
查看>>
关于ProjectServer定制化项目中心页面
查看>>
使用Collectd + InfluxDB + Grafana进行JMX监控
查看>>
Linux下tar,zip命令详解
查看>>
C#垃圾回收机制
查看>>
31、任务三十一——表单联动
查看>>
python之hasattr、getattr和setattr函数
查看>>
maven使用阿里镜像配置文件
查看>>