hdu3397 Sequence operation 线段树

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 }

 

posted @ 2019-11-07 19:17  麻辣猪仔  阅读(178)  评论(0编辑  收藏  举报