线段树-各种操作杂烩题 (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
", _query_sum(1)); continue; }
133         if (OP == 5) { printf("%d
", _query_con(1)); continue; }
134     }
135     return 0;
136 }
View Code
原文地址:https://www.cnblogs.com/ghcred/p/8296101.html