SHOI2015 脑洞治疗仪

以前就这道题跟大佬讨论过,我觉得就是暴力填充,他说二分位置填充,后来发现我的方法麻烦到了极点...果断二分,还是打了6K......

题意:有个01序列,要求支持以下操作:

1.区间赋0

2.区间求和

3.把区间内前k个0变成1

一看就是线段树...

操作三只需要二分求出位置即可。

总复杂度nlog²n,最慢的点卡着0.92s过了。

  1 #include <cstdio>
  2 #include <algorithm>
  3 const int N = 200010;
  4 
  5 struct SegmentTree {
  6     int sum[N << 2], left[N << 2], right[N << 2], large[N << 2], tag[N << 2];
  7 
  8     inline void pushup(int l, int r, int o) {
  9         if(l == r) {
 10             left[o] = right[o] = large[o] = sum[o] ^ 1;
 11             return;
 12         }
 13         int mid = (l + r) >> 1;
 14         int ls = o << 1;
 15         int rs = ls | 1;
 16 
 17         sum[o] = sum[ls] + sum[rs];
 18         large[o] = std::max(large[ls], large[rs]);
 19         large[o] = std::max(large[o], left[rs] + right[ls]);
 20         if(!sum[ls]) {
 21             left[o] = mid - l + 1 + left[rs];
 22         }
 23         else {
 24             left[o] = left[ls];
 25         }
 26         if(!sum[rs]) {
 27             right[o] = r - mid + right[ls];
 28         }
 29         else {
 30             right[o] = right[rs];
 31         }
 32         return;
 33     }
 34     inline void pushdown(int l, int r, int o) {
 35         if(l == r) {
 36             return;
 37         }
 38         int mid = (l + r) >> 1;
 39         int ls = o << 1;
 40         int rs = ls | 1;
 41         if(tag[o] == 1) {
 42             sum[ls] = mid - l + 1;
 43             sum[rs] = r - mid;
 44             tag[ls] = tag[rs] = 1;
 45             left[ls] = left[rs] = 0;
 46             right[ls] = right[rs] = 0;
 47             large[ls] = large[rs] = 0;
 48         }
 49         else if(!tag[o]) {
 50             sum[ls] = sum[rs] = 0;
 51             tag[ls] = tag[rs] = 0;
 52             left[ls] = right[ls] = large[ls] = mid - l + 1;
 53             left[rs] = right[rs] = large[rs] = r - mid;
 54         }
 55         tag[o] = -1;
 56         return;
 57     }
 58     void cancel(int L, int R, int l, int r, int o) {
 59         if(L <= l && r <= R) {
 60             tag[o] = sum[o] = 0;
 61             left[o] = right[o] = large[o] = r - l + 1;
 62             return;
 63         }
 64         pushdown(l, r, o);
 65         int mid = (l + r) >> 1;
 66         if(L <= mid) {
 67             cancel(L, R, l, mid, o << 1);
 68         }
 69         if(mid < R) {
 70             cancel(L, R, mid + 1, r, o << 1 | 1);
 71         }
 72         pushup(l, r, o);
 73         return;
 74     }
 75     int getsum(int L, int R, int l, int r, int o) {
 76         if(L <= l && r <= R) {
 77             return sum[o];
 78         }
 79         if(r < L || R < l) {
 80             return 0;
 81         }
 82         pushdown(l, r, o);
 83         int mid = (l + r) >> 1;
 84         return getsum(L, R, l, mid, o << 1) + getsum(L, R, mid + 1, r, o << 1 | 1);
 85     }
 86     void add(int L, int R, int l, int r, int o) {
 87         pushdown(l, r, o);
 88         if(L <= l && r <= R) {
 89             tag[o] = 1;
 90             sum[o] = r - l + 1;
 91             left[o] = right[o] = large[o] = 0;
 92             return;
 93         }
 94         int mid = (l + r) >> 1;
 95         if(L <= mid) {
 96             add(L, R, l, mid, o << 1);
 97         }
 98         if(mid < R) {
 99             add(L, R, mid + 1, r, o << 1 | 1);
100         }
101         pushup(l, r, o);
102         return;
103     }
104     void ask(int L, int R, int l, int r, int o, int &la, int &ra, int &ans) {
105         pushdown(l, r, o);
106         if(L == l && r == R) {
107             la = left[o];
108             ra = right[o];
109             ans = large[o];
110             return;
111         }
112         int mid = (l + r) >> 1;
113         int ls = o << 1;
114         int rs = ls | 1;
115         if(R <= mid) {
116             ask(L, R, l, mid, ls, la, ra, ans);
117             return;
118         }
119         if(mid < L) {
120             ask(L, R, mid + 1, r, rs, la, ra, ans);
121             return;
122         }
123         int A = -1;
124         int B = A, C = A, D = A, E = A, F = A;
125         if(L != l && r != R) {
126             ask(L, mid, l, mid, ls, A, B, C);
127             ask(mid + 1, R, mid + 1, r, rs, D, E, F);
128             ans = std::max(C, F);
129             ans = std::max(ans, B + D);
130             return;
131         }
132         if(R == r) {
133             ask(L, mid, l, mid, ls, A, B, C);
134             ans = std::max(large[rs], C);
135             ans = std::max(ans, B + left[rs]);
136             if(!sum[rs]) {
137                 ra = r - mid + B;
138             }
139             else {
140                 ra = right[rs];
141             }
142             return;
143         }
144         if(L == l) {
145             ask(mid + 1, R, mid + 1, r, rs, A, B, C);
146             ans = std::max(large[ls], C);
147             ans = std::max(ans, right[ls] + A);
148             if(!sum[ls]) {
149                 la = mid - l + 1 + A;
150             }
151             else {
152                 la = left[ls];
153             }
154             return;
155         }
156         printf("ERROR! ");
157         return;
158     }
159     void build(int l, int r, int o) {
160         tag[o] = -1;
161         if(l == r) {
162             sum[o] = 1;
163             left[o] = right[o] = large[o] = 0;
164             return;
165         }
166         int mid = (l + r) >> 1;
167         build(l, mid, o << 1);
168         build(mid + 1, r, o << 1 | 1);
169         pushup(l, r, o);
170         return;
171     }
172 }T;
173 
174 int main() {
175     int n, m;
176     scanf("%d%d", &n, &m);
177     T.build(1, n, 1);
178     int x, y, xx, yy, f;
179     while(m--) {
180         scanf("%d%d%d", &f, &x, &y);
181         if(!f) {
182             T.cancel(x, y, 1, n, 1);
183         }
184         else if(f == 2) {
185             int ans;
186             T.ask(x, y, 1, n, 1, xx, yy, ans);
187             printf("%d\n", ans);
188         }
189         else {
190             scanf("%d%d", &xx, &yy);
191             int t = T.getsum(x, y, 1, n, 1);
192             T.cancel(x, y, 1, n, 1);
193             if(t >= yy - xx + 1 - T.getsum(xx, yy, 1, n, 1)) {
194                 T.add(xx, yy, 1, n, 1);
195                 continue;
196             }
197             if(!t) {
198                 continue;
199             }
200             int l = xx + t - 1, r = yy - 1, mid;
201             while(l < r) {
202                 mid = (l + r) >> 1;
203                 //printf("getsum %d %d : %d \n", xx, mid, T.getsum(xx, mid, 1, n, 1));
204                 if(mid - xx + 1 - T.getsum(xx, mid, 1, n, 1) < t) {
205                     l = mid + 1;
206                 }
207                 else {
208                     r = mid;
209                 }
210             }
211             //printf("t = %d \n add: %d %d \n", t, xx, r);
212             T.add(xx, r, 1, n, 1);
213         }
214     }
215 
216     return 0;
217 }
AC代码

 

posted @ 2018-07-25 22:07  garage  阅读(174)  评论(0编辑  收藏  举报