之前就這道題跟大佬討論過,我以爲就是暴力填充,他說二分位置填充,後來發現個人方法麻煩到了極點...果斷二分,仍是打了6K......ide
題意:有個01序列,要求支持如下操做:ui
1.區間賦0spa
2.區間求和code
3.把區間內前k個0變成1blog
一看就是線段樹...get
操做三隻須要二分求出位置便可。it
總複雜度nlog²n,最慢的點卡着0.92s過了。io
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 }