luogu P2572 [SCOI2010]序列操作
这个题我写了差不多一周吧……
终于改成了一个能在考试的时候写完的版本
大量的区间操作 1e5
显然线段树解决
确实是板子题 但是极其难调……
最后听rabbithu学姐讲了一下才用“结构体解决一切”做完本题
几个要点:
1、覆盖标记高于反转标记
也就是pushdown的时候先放覆盖 同时清空反转
然后update反转的时候在覆盖标记上修改就OK
2、查询必须“精准扶贫”
由于要维护最长连续 必须保证query回溯的和就是目标区间
结构体重载+号完美的解决了区间合并的问题
然后update的时候是可以二分的
Code:
1 // luogu-judger-enable-o2 2 // luogu-judger-enable-o2 3 #include <cstdio> 4 #include <cmath> 5 #include <cstring> 6 #include <algorithm> 7 #define space putchar(' ') 8 #define enter putchar('\n') 9 typedef long long ll; 10 using namespace std; 11 template <class T> 12 void read(T &x){ 13 char c; 14 bool op = 0; 15 while(c = getchar(), c < '0' || c > '9') 16 if(c == '-') op = 1; 17 x = c - '0'; 18 while(c = getchar(), c >= '0' && c <= '9') 19 x = x * 10 + c - '0'; 20 if(op) x = -x; 21 } 22 template <class T> 23 void write(T x){ 24 if(x < 0) putchar('-'), x = -x; 25 if(x >= 10) write(x / 10); 26 putchar('0' + x % 10); 27 } 28 29 const int N = 400005; 30 int n, m, a[N], chg[N]; 31 bool rev[N]; 32 struct Data{ 33 int sum, sa, sl, sr; 34 bool all; 35 Data(){} 36 Data(int len){ 37 sum = sa = sl = sr = len, all = len > 0; 38 } 39 Data operator + (const Data &b) const { 40 Data ret; 41 ret.sum = sum + b.sum; 42 ret.sa = max(max(sa, b.sa), sr + b.sl); 43 ret.sl = all ? sl + b.sl : sl; 44 ret.sr = b.all ? sr + b.sr : b.sr; 45 ret.all = all & b.all; 46 return ret; 47 } 48 } data[N][2], ans; 49 50 void modify(int k, int l, int r, int x){ 51 if(~x){ 52 if(rev[k]) rev[k] = 0; 53 chg[k] = x; 54 data[k][x] = Data(r - l + 1); 55 data[k][x ^ 1] = Data(0); 56 } 57 else{ 58 if(~chg[k]) chg[k] ^= 1; 59 else rev[k] ^= 1; 60 swap(data[k][0], data[k][1]); 61 } 62 } 63 void pushdown(int k, int l, int r){ 64 int mid = (l + r) >> 1; 65 if(~chg[k]) modify(k << 1, l, mid, chg[k]), modify(k << 1 | 1, mid + 1, r, chg[k]); 66 if(rev[k]) modify(k << 1, l, mid, -1), modify(k << 1 | 1, mid + 1, r, -1); 67 chg[k] = -1, rev[k] = 0; 68 } 69 void pushup(int k){ 70 data[k][0] = data[k << 1][0] + data[k << 1 | 1][0]; 71 data[k][1] = data[k << 1][1] + data[k << 1 | 1][1]; 72 } 73 void build(int k, int l, int r){ 74 chg[k] = -1, rev[k] = 0; 75 if(l == r) return data[k][a[l]] = Data(1), data[k][a[l] ^ 1] = Data(0), void(); 76 int mid = (l + r) >> 1; 77 build(k << 1, l, mid); 78 build(k << 1 | 1, mid + 1, r); 79 pushup(k); 80 } 81 void change(int k, int l, int r, int ql, int qr, int x){ 82 if(ql <= l && qr >= r) return modify(k, l, r, x); 83 pushdown(k, l, r); 84 int mid = (l + r) >> 1; 85 if(ql <= mid) change(k << 1, l, mid, ql, qr, x); 86 if(qr > mid) change(k << 1 | 1, mid + 1, r, ql, qr, x); 87 pushup(k); 88 } 89 Data query(int k, int l, int r, int ql, int qr){ 90 if(ql <= l && qr >= r) return data[k][1]; 91 pushdown(k, l, r); 92 int mid = (l + r) >> 1; 93 if(qr <= mid) return query(k << 1, l, mid, ql, qr); 94 if(ql > mid) return query(k << 1 | 1, mid + 1, r, ql, qr); 95 return query(k << 1, l, mid, ql, qr) + query(k << 1 | 1, mid + 1, r, ql, qr); 96 } 97 98 int main(){ 99 100 read(n), read(m); 101 for(int i = 1; i <= n; i++) read(a[i]); 102 build(1, 1, n); 103 int op, l, r; 104 while(m--){ 105 read(op), read(l), read(r), l++, r++; 106 if(op < 3) change(1, 1, n, l, r, op == 2 ? -1 : op); 107 else{ 108 ans = query(1, 1, n, l, r); 109 if(op == 3) write(ans.sum); 110 else write(ans.sa); 111 enter; 112 } 113 } 114 115 return 0; 116 }
完结撒花~
> 别忘了 总有人在等着你