线段树-各种操作杂烩题 (SCOI2010 DAY2)
NKOJ2645
第一次做这种儿子并不一定直接继承父亲节点 lazy ,而要分类讨论的线段树题。学习学习。
1 #include <stdio.h> 2 #include <algorithm> 3 4 using namespace std; 5 6 const int _N = 800000; 7 const int lazy_helper[] = {3, 2, 1, 0}; 8 9 int l[_N], r[_N], sum[_N], mx1[_N], mx0[_N], cl1[_N], cl0[_N], cr1[_N], cr0[_N], lazy[_N]; 10 int D, V, S, T, OP, n, m; 11 12 void _build(int p, int s, int t) 13 { 14 l[p] = s, r[p] = t; 15 if (s == t) return; 16 int mid = s+t>>1; 17 _build(p<<1, s, mid), _build(p<<1|1, mid+1, t); 18 return; 19 } 20 21 void _maintain(int p) 22 { 23 int mid = l[p]+r[p] >> 1; 24 sum[p] = sum[p<<1] + sum[p<<1|1]; 25 mx1[p] = max(max(mx1[p<<1], mx1[p<<1|1]), cr1[p<<1]+cl1[p<<1|1]); 26 mx0[p] = max(max(mx0[p<<1], mx0[p<<1|1]), cr0[p<<1]+cl0[p<<1|1]); 27 cl1[p] = mx1[p<<1]==mid-l[p]+1 ? mx1[p<<1]+cl1[p<<1|1] : cl1[p<<1]; 28 cr1[p] = mx1[p<<1|1]==r[p]-mid ? mx1[p<<1|1]+cr1[p<<1] : cr1[p<<1|1]; 29 cl0[p] = mx1[p<<1]==0 ? mid-l[p]+1+cl0[p<<1|1] : cl0[p<<1]; 30 cr0[p] = mx1[p<<1|1]==0 ? r[p]-mid+cr0[p<<1] : cr0[p<<1|1]; 31 return; 32 } 33 34 inline void _set_1(int p, bool g) { sum[p] = mx1[p] = cl1[p] = cr1[p] = (g ? r[p]-l[p]+1 : 0); return; } 35 36 inline void _set_0(int p, bool g) { mx0[p] = cl0[p] = cr0[p] = (g ? r[p]-l[p]+1 : 0); return; } 37 38 inline void _set(int p, bool g) { _set_1(p, g); _set_0(p, !g); return; } 39 40 inline void _exchange(int p) 41 { 42 swap(mx1[p], mx0[p]), swap(cl1[p], cl0[p]), swap(cr1[p], cr0[p]); 43 sum[p] = r[p]-l[p]+1-sum[p]; 44 return; 45 } 46 47 //D V 48 void _modify_single(int p) 49 { 50 if (l[p] == r[p]) { _set(p, V); return; } 51 int mid = l[p]+r[p] >> 1; 52 if (D <= mid) _modify_single(p<<1); 53 else _modify_single(p<<1|1); 54 _maintain(p); 55 return; 56 } 57 58 void _pushdown(int p) 59 { 60 if (l[p] == r[p]) { lazy[p] = 0; return; } 61 switch (lazy[p]) { 62 case 1: _set(p<<1, 0), _set(p<<1|1, 0); break; 63 case 2: _set(p<<1, 1), _set(p<<1|1, 1); break; 64 case 3: _exchange(p<<1), _exchange(p<<1|1); break; 65 } 66 if (lazy[p] != 3) lazy[p<<1] = lazy[p<<1|1] = lazy[p]; 67 else lazy[p<<1] = lazy_helper[lazy[p<<1]], lazy[p<<1|1] = lazy_helper[lazy[p<<1|1]]; 68 lazy[p] = 0; 69 return; 70 } 71 72 //S T OP 73 void _modify(int p) 74 { 75 if (S <= l[p] && r[p] <= T) { _set(p, OP == 2); lazy[p] = OP; return; } 76 if (lazy[p]) _pushdown(p); 77 int mid = l[p]+r[p] >> 1; 78 if (S <= mid && T >= l[p]) _modify(p<<1); 79 if (S <= r[p] && T > mid) _modify(p<<1|1); 80 _maintain(p); 81 return; 82 } 83 84 //S T OP 85 void _turnard(int p) 86 { 87 if (S <= l[p] && r[p] <= T) { _exchange(p); lazy[p] = lazy_helper[lazy[p]]; return; } 88 if (lazy[p]) _pushdown(p); 89 int mid = l[p]+r[p] >> 1; 90 if (S <= mid && T >= l[p]) _turnard(p<<1); 91 if (S <= r[p] && T > mid) _turnard(p<<1|1); 92 _maintain(p); 93 return; 94 } 95 96 //S T 97 int _query_sum(int p) 98 { 99 if (S <= l[p] && r[p] <= T) return sum[p]; 100 if (lazy[p]) _pushdown(p); 101 int mid = l[p]+r[p] >> 1, tmp_cnt = 0; 102 if (S <= mid && T >= l[p]) tmp_cnt += _query_sum(p<<1); 103 if (S <= r[p] && T > mid) tmp_cnt += _query_sum(p<<1|1); 104 return tmp_cnt; 105 } 106 107 //S T 108 int _query_con(int p) 109 { 110 if (S <= l[p] && r[p] <= T) return mx1[p]; 111 if (lazy[p]) _pushdown(p); 112 int mid = l[p]+r[p] >> 1, tmp_mx = -1218; 113 if (S <= mid && T >= l[p]) tmp_mx = max(tmp_mx, _query_con(p<<1)); 114 if (S <= r[p] && T > mid) tmp_mx = max(tmp_mx, _query_con(p<<1|1)); 115 if (S <= mid && T > mid) tmp_mx = max(tmp_mx, min(mid-S+1, cr1[p<<1])+min(T-mid, cl1[p<<1|1])); 116 return tmp_mx; 117 } 118 119 int main() 120 { 121 int i; 122 scanf("%d%d", &n, &m); 123 _build(1, 1, n); 124 for (i = 1; i <= n; ++i) { 125 scanf("%d", &V); 126 D = i, _modify_single(1); 127 } 128 while (m--) { 129 scanf("%d%d%d", &OP, &S, &T), ++S, ++T, ++OP; 130 if (OP == 1 || OP == 2) { _modify(1); continue; } 131 if (OP == 3) { _turnard(1); continue; } 132 if (OP == 4) { printf("%d\n", _query_sum(1)); continue; } 133 if (OP == 5) { printf("%d\n", _query_con(1)); continue; } 134 } 135 return 0; 136 }