Codeforces Round #104 (Div. 1) E. Lucky Queries 线段树
链接:
http://codeforces.com/contest/145/problem/E
题意:
维护一个只有数字4和7的数列,以下有两种操作:
1.将[l,r]区间4变为7,7变为4。
2.询问全局最长不下降子序列的长度。
输出所有2操作的答案
题解:
线段树维护。
维护四个信息:
1.区间4的个数。
2.区间7的个数。
3.区间不降子序列的长度。
4.区间不升子序列的长度。
具体更新的看代码
代码:
31 int n, m; 32 string s; 33 struct Node { 34 int f, s, fs, sf, rev; 35 }Tree[MAXN << 2]; 36 37 void pushup(int rt) { 38 Tree[rt].f = Tree[rt << 1].f + Tree[rt << 1 | 1].f; 39 Tree[rt].s = Tree[rt << 1].s + Tree[rt << 1 | 1].s; 40 Tree[rt].fs = max(Tree[rt << 1].f + Tree[rt << 1 | 1].fs, Tree[rt << 1].fs + Tree[rt << 1 | 1].s); 41 Tree[rt].sf = max(Tree[rt << 1].s + Tree[rt << 1 | 1].sf, Tree[rt << 1].sf + Tree[rt << 1 | 1].f); 42 } 43 44 void pushdown(int rt) { 45 if (Tree[rt].rev) { 46 swap(Tree[rt << 1].f, Tree[rt << 1].s); 47 swap(Tree[rt << 1 | 1].f, Tree[rt << 1 | 1].s); 48 swap(Tree[rt << 1].sf, Tree[rt << 1].fs); 49 swap(Tree[rt << 1 | 1].sf, Tree[rt << 1 | 1].fs); 50 Tree[rt << 1].rev ^= 1; 51 Tree[rt << 1 | 1].rev ^= 1; 52 Tree[rt].rev = 0; 53 } 54 } 55 56 void build(int l, int r, int rt) { 57 if (l == r) { 58 if (s[l - 1] == '4') Tree[rt].f = 1; 59 else Tree[rt].s = 1; 60 Tree[rt].fs = Tree[rt].sf = 1; 61 return; 62 } 63 int m = (l + r) >> 1; 64 build(lson); 65 build(rson); 66 pushup(rt); 67 } 68 69 void update(int L, int R, int l, int r, int rt) { 70 if (L <= l && r <= R) { 71 Tree[rt].rev ^= 1; 72 swap(Tree[rt].f, Tree[rt].s); 73 swap(Tree[rt].fs, Tree[rt].sf); 74 return; 75 } 76 pushdown(rt); 77 int m = (l + r) >> 1; 78 if (L <= m) update(L, R, lson); 79 if (R > m) update(L, R, rson); 80 pushup(rt); 81 } 82 83 int main() { 84 ios::sync_with_stdio(false), cin.tie(0); 85 cin >> n >> m >> s; 86 build(1, n, 1); 87 while (m--) { 88 string s; 89 cin >> s; 90 if (s == "switch") { 91 int l, r; 92 cin >> l >> r; 93 update(l, r, 1, n, 1); 94 } 95 else cout << Tree[1].fs << endl; 96 } 97 return 0; 98 }