LOJ #2037. 「SHOI2015」脑洞治疗仪

Posted 心之所向 素履以往

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LOJ #2037. 「SHOI2015」脑洞治疗仪相关的知识,希望对你有一定的参考价值。

                                       #2037. 「SHOI2015」脑洞治疗仪

题目描述

曾经发明了自动刷题机的发明家 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 的问题:在大脑某个区间中最大的连续脑洞区域有多大。

输入格式

第一行两个整数 nm,表示 SHTSC 的大脑可分为从 1 到 n 编号的 n 个连续区域,有 m 个操作。

以下 m 行每行是下列三种格式之一:

  • 0 l r:SHTSC 挖了一个范围为 [l,r] 的脑洞。
  • 1 l0 r0 l1 r1:SHTSC 进行了一次脑洞治疗,用从 l0?? 到 r0的脑组织修补 l1到 r1的脑洞。
  • 2 l r :SHTSC 询问 [l,r]区间内最大的脑洞有多大。

上述区间均在 [1,n] 范围内。

输出格式

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

样例

样例输入

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

样例输出

3
3
6
6

数据范围与提示

对于 20% 的数据,n,m≤100
对于 50% 的数据,n,m≤20000
对于 100%的数据,n,m≤200000

 

一眼线段树 但是操作太恶心。。。

维护5个域 ml 区间包含左端点最长0串 

            mr 区间包含右端点最长0串

     mx 区间最长0串

sum 区间1的个数 len区间长度(这个不一定要维护 用结构体可以不用写。)

两种  tag 标记 tag=1 区间赋值为1 

         tag=0 区间赋值为 0

 

一个是区间赋值为 0 简单的区间修改+标记下放 

区间查询 1的个数

区间间从左向右 赋值为1   从每个 0的个数小于当前剩余1个个数的区间填数 每次只将一个小区间填满

区间查询最长0串  这里需要一个辅助变量 因为线段树普通查询只是返回每个区间的最大值

如果我们查询了两个区间 目标区间的最大值恰好是左区间的mr+右区间的ml 这种情况是会出错的 

就像 1 1 1  0 0 0 1 一共7个数 要查询 [1,5]的1最大值 线段树查询会先找[1,4] 再找 [5,5] 然后返回 两个区间的最大值 

但是 [4,5] 是连续的 所以我们用help变量来记录 每个区间从右端点开始的最大值 与ans比较 再更新

 

技术分享
  1 #include <cstdio>
  2 #include <cctype>
  3 
  4 const int MAXN=200010;
  5 
  6 int n,m,ans,help;
  7 
  8 struct SegmentTree {
  9     int l,r;
 10     int tag;
 11     int mx,ml,mr;
 12     int sum,len;
 13 };
 14 SegmentTree t[MAXN<<2];
 15 
 16 inline void read(int&x) {
 17     int f=1;register char c=getchar();
 18     for(x=0;!isdigit(c);c==-&&(f=-1),c=getchar());
 19     for(;isdigit(c);x=x*10+c-48,c=getchar());
 20     x=x*f;
 21 }
 22 
 23 inline int max(int a,int b) {return a<b?b:a;}
 24 
 25 inline void up(int now) {
 26     t[now].sum=t[now<<1].sum+t[now*2+1].sum;
 27     t[now].mx=max(t[now<<1].mx,t[now*2+1].mx);
 28     t[now].ml=t[now<<1].ml;
 29     t[now].mr=t[now*2+1].mr;
 30     if(t[now<<1].ml==t[now<<1].len) t[now].ml=t[now<<1].len+t[now*2+1].ml;
 31     if(t[now*2+1].mr==t[now*2+1].len) t[now].mr=t[now*2+1].len+t[now<<1].mr;
 32     t[now].mx=max((max(t[now].ml,t[now].mr),t[now<<1].mr+t[now*2+1].ml),t[now].mx);
 33 }
 34 
 35 inline void down(int now) {
 36     t[now<<1].tag=t[now<<1|1].tag=t[now].tag;
 37     t[now<<1].sum=(t[now<<1].r-t[now<<1].l+1)*t[now].tag;
 38     t[now<<1|1].sum=(t[now<<1|1].r-t[now<<1|1].l+1)*t[now].tag;
 39     if(t[now].tag) t[now<<1].ml=t[now<<1].mr=t[now<<1].mx=0,t[now<<1|1].ml=t[now<<1|1].mr=t[now<<1|1].mx=0; 
 40     else t[now<<1].ml=t[now<<1].mr=t[now<<1].mx=t[now<<1].len,t[now<<1|1].ml=t[now<<1|1].mr=t[now<<1|1].mx=t[now<<1|1].len; 
 41     t[now].tag=-1;
 42 }
 43 
 44 void build_tree(int now,int l,int r) {
 45     t[now].l=l;t[now].r=r;
 46     t[now].len=r-l+1;
 47     t[now].tag=-1;
 48     if(l==r) {
 49         t[now].sum=1;
 50         return;
 51     }
 52     int mid=(l+r)>>1;
 53     build_tree(now<<1,l,mid);
 54     build_tree(now<<1|1,mid+1,r);
 55     t[now].sum=t[now<<1].sum+t[now<<1|1].sum;
 56 }
 57 
 58 void modify(int now,int l,int r) { 
 59     if(l<=t[now].l&&r>=t[now].r) {
 60         t[now].tag=0;
 61         t[now].sum=0;
 62         t[now].ml=t[now].mr=t[now].mx=t[now].len;
 63         return;
 64     }
 65     if(t[now].tag!=-1) down(now);
 66     int mid=(t[now].l+t[now].r)>>1;
 67     if(l<=mid) modify(now<<1,l,r);
 68     if(r>mid) modify(now<<1|1,l,r);
 69     up(now);
 70 } 
 71 
 72 void modify2(int now,int l,int r,int &s) {
 73     if(!s) return;
 74     if(l<=t[now].l&&r>=t[now].r&&s>=t[now].len-t[now].sum) {
 75         s-=t[now].len-t[now].sum;
 76         t[now].tag=1;
 77         t[now].sum=t[now].len;
 78         t[now].mx=t[now].ml=t[now].mr=0;
 79         return;
 80     }
 81     if(t[now].tag!=-1) down(now);
 82     int mid=(t[now].l+t[now].r)>>1;
 83     if(l<=mid) modify2(now<<1,l,r,s);
 84     if(r>mid) modify2(now<<1|1,l,r,s);
 85     up(now);
 86 }
 87 
 88 void query(int now,int l,int r) {
 89     if(l<=t[now].l&&r>=t[now].r) {
 90         ans=max(ans,t[now].mx);
 91         ans=max(ans,help+t[now].ml);
 92         if(t[now].mr==t[now].len) help+=t[now].len;
 93         else help=t[now].mr;
 94         return;
 95     }
 96     if(t[now].tag!=-1) down(now);
 97     int mid=(t[now].l+t[now].r)>>1;
 98     if(l<=mid) query(now<<1,l,r);
 99     if(r>mid) query(now<<1|1,l,r);
100 }
101 
102 int _query(int now,int l,int r) {
103     int ans=0;
104     if(l<=t[now].l&&r>=t[now].r) return t[now].sum;
105     if(t[now].tag!=-1) down(now);
106     int mid=(t[now].l+t[now].r)>>1;
107     if(l<=mid) ans+=_query(now<<1,l,r);
108     if(r>mid) ans+=_query(now<<1|1,l,r);
109     return ans;
110 }
111 
112 int hh() {
113     read(n);read(m);
114     build_tree(1,1,n);
115     for(int type,x,y,L,R,i=1;i<=m;++i) {
116         read(type);read(x);read(y);
117         if(!type) modify(1,x,y);
118         else if(type==2) {
119             ans=0,help=0;
120             query(1,x,y);
121             printf("%d\n",ans);
122         }
123         else {
124             read(L);read(R);
125             int t=_query(1,x,y);
126             modify(1,x,y);
127             modify2(1,L,R,t);
128         }
129     }
130     return 0;
131 }
132 
133 int sb=hh();
134 int main(int argc,char**argv) {;}
代码

 

以上是关于LOJ #2037. 「SHOI2015」脑洞治疗仪的主要内容,如果未能解决你的问题,请参考以下文章

bzoj4592 [Shoi2015]脑洞治疗仪

BZOJ4592[Shoi2015]脑洞治疗仪 线段树

[SHOI2015]脑洞治疗仪

[SHOI2015]脑洞治疗仪(恶心的线段树,区间最大子段和)

SHOI2015脑洞治疗仪(恶心的线段树,区间最大子段和)

[SHOI 2015] 脑洞治疗仪