hdu3397 Sequence operation 线段树
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn = 1e6+5; 4 struct node { 5 /// l,r表示当前结点区间范围[l,r] 6 int l, r; 7 /// val=0时为全0标志,表示区间[l,r]的值全为0 8 /// val=1时为全1标志,表示区间[l,r]的值全为1 9 /// val=-1时则代表无操作 10 /// xor为异或标志,表示区间[l,r]的值取异或操作 11 int val, Xor; 12 /// lmax_0表示区间[l,r]从左往右开始连续0的个数 13 /// rmax_0表示区间[l,r]从右往左开始连续0的个数 14 /// max_0表示当前区间最大连续0的个数 15 int lmax_0, rmax_0, max_0, sum_0; 16 int lmax_1, rmax_1, max_1, sum_1; 17 /// 得到当前区间长度 18 int len() { return r-l+1; } 19 20 /// 更新操作,val_代表01操作,xor_代表异或操作 21 void change(int val_, int Xor_) { 22 /// [l,r]全置为0 23 if (val_ == 0) { 24 lmax_0 = rmax_0 = max_0 = sum_0 = len(); 25 lmax_1 = rmax_1 = max_1 = sum_1 = 0; 26 val = 0, Xor = 0; 27 } 28 /// [l,r]全置为1 29 else if (val_ == 1) { 30 lmax_0 = rmax_0 = max_0 = sum_0 = 0; 31 lmax_1 = rmax_1 = max_1 = sum_1 = len(); 32 val = 1, Xor = 0; 33 } 34 /// [l,r]全异或 35 if (Xor_ == 1) { 36 swap(lmax_0,lmax_1); swap(rmax_0,rmax_1); 37 swap(max_0,max_1); swap(sum_0,sum_1); 38 Xor ^= 1; 39 } 40 } 41 }tree[maxn*4]; 42 int a[maxn]; 43 void pushup(node &fa, node &ls, node &rs) { 44 /// 父节点的左边最长0串=左子树的左边最长0串 45 fa.lmax_0 = ls.lmax_0, fa.rmax_0 = rs.rmax_0; 46 fa.lmax_1 = ls.lmax_1, fa.rmax_1 = rs.rmax_1; 47 /// 父节点0的数量=左子树0的数量+右子树0的数量 48 fa.sum_0 = ls.sum_0+rs.sum_0; 49 fa.sum_1 = ls.sum_1+rs.sum_1; 50 /// 父节点最大连续0串等于左右子树里面中最大连续0串的最大值 51 /// 或者是左子树从右开始的0串+右子树从左开始的0串之和 52 fa.max_0 = max(max(ls.max_0,rs.max_0), ls.rmax_0+rs.lmax_0); 53 fa.max_1 = max(max(ls.max_1,rs.max_1), ls.rmax_1+rs.lmax_1); 54 55 /// 如果左子树整串都为0串 56 if (ls.len() == ls.lmax_0) fa.lmax_0 += rs.lmax_0; 57 if (ls.len() == ls.lmax_1) fa.lmax_1 += rs.lmax_1; 58 if (rs.len() == rs.rmax_0) fa.rmax_0 += ls.rmax_0; 59 if (rs.len() == rs.rmax_1) fa.rmax_1 += ls.rmax_1; 60 } 61 void pushdown(int rt) { 62 if (tree[rt].val != -1 || tree[rt].Xor) { 63 tree[rt*2].change(tree[rt].val,tree[rt].Xor); 64 tree[rt*2+1].change(tree[rt].val,tree[rt].Xor); 65 tree[rt].val = -1, tree[rt].Xor = 0; 66 } 67 } 68 void build(int rt, int l, int r) { 69 /// 结点初始化 70 tree[rt].l = l, tree[rt].r = r; 71 tree[rt].lmax_0 = tree[rt].rmax_0 = 0; 72 tree[rt].lmax_1 = tree[rt].rmax_1 = 0; 73 tree[rt].max_0 = tree[rt].max_1 = 0; 74 tree[rt].sum_0 = tree[rt].sum_1 = 0; 75 tree[rt].Xor = 0, tree[rt].val = -1; 76 /// 如果是叶子结点 77 if (l == r) { 78 tree[rt].change(a[l],0); 79 return; 80 } 81 int mid = (l+r)/2; 82 build(rt*2,l,mid); 83 build(rt*2+1,mid+1,r); 84 pushup(tree[rt],tree[rt*2],tree[rt*2+1]); 85 } 86 void update(int rt, int l, int r, int op) { 87 int L = tree[rt].l, R = tree[rt].r; 88 if (l <= L && R <= r) { 89 /// 根据op执行不同操作 90 if (op == 0 || op == 1) tree[rt].change(op,0); 91 else if (op == 2) tree[rt].change(-1,1); 92 return; 93 } 94 pushdown(rt); 95 int mid = (L+R)/2; 96 if (mid >= l) update(rt*2,l,r,op); 97 if (mid < r) update(rt*2+1,l,r,op); 98 pushup(tree[rt],tree[rt*2],tree[rt*2+1]); 99 } 100 int query(int rt, int l, int r, int op) { 101 int L = tree[rt].l, R = tree[rt].r; 102 if (l <= L && R <= r) { 103 if (op == 3) return tree[rt].sum_1; 104 else if (op == 4) return tree[rt].max_1; 105 } 106 int mid = (L+R)/2; 107 pushdown(rt); 108 if (r <= mid) return query(rt*2,l,r,op); 109 else if (l > mid) return query(rt*2+1,l,r,op); 110 else { 111 int max1 = query(rt*2,l,r,op); 112 int max2 = query(rt*2+1,l,r,op); 113 if (op == 3) return max1+max2; 114 int max3 = min(tree[rt*2].r-l+1,tree[rt*2].rmax_1)+min(r-tree[rt*2+1].l+1,tree[rt*2+1].lmax_1); 115 return max(max(max1,max2),max3); 116 } 117 } 118 int main() { 119 int t; scanf("%d",&t); 120 while (t--) { 121 int n, m; scanf("%d%d",&n,&m); 122 for (int i = 0; i < n; ++i) 123 scanf("%d",&a[i]); 124 build(1,0,n-1); 125 while (m--) { 126 int op, a, b; 127 scanf("%d%d%d",&op,&a,&b); 128 if (op == 0 || op == 1 || op == 2) update(1,a,b,op); 129 else printf("%d\n",query(1,a,b,op)); 130 } 131 } 132 return 0; 133 }