luogu P2572 [SCOI2010]序列操作
生活随笔
收集整理的這篇文章主要介紹了
luogu P2572 [SCOI2010]序列操作
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
傳送門
這個(gè)題我寫了差不多一周吧……
終于改成了一個(gè)能在考試的時(shí)候?qū)懲甑陌姹?/p>
大量的區(qū)間操作 1e5
顯然線段樹解決?
確實(shí)是板子題 但是極其難調(diào)……
最后聽rabbithu學(xué)姐講了一下才用“結(jié)構(gòu)體解決一切”做完本題
幾個(gè)要點(diǎn):
1、覆蓋標(biāo)記高于反轉(zhuǎn)標(biāo)記
也就是pushdown的時(shí)候先放覆蓋 同時(shí)清空反轉(zhuǎn)
然后update反轉(zhuǎn)的時(shí)候在覆蓋標(biāo)記上修改就OK
2、查詢必須“精準(zhǔn)扶貧”
由于要維護(hù)最長(zhǎng)連續(xù) 必須保證query回溯的和就是目標(biāo)區(qū)間
結(jié)構(gòu)體重載+號(hào)完美的解決了區(qū)間合并的問題
然后update的時(shí)候是可以二分的
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 } View Code完結(jié)撒花~
轉(zhuǎn)載于:https://www.cnblogs.com/yuyanjiaB/p/9754119.html
總結(jié)
以上是生活随笔為你收集整理的luogu P2572 [SCOI2010]序列操作的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 结对编程小项目实现 Python+PyQ
- 下一篇: 编写uwsgi后台启动文件