BZOJ1858 [Scoi2010]序列操作(线段树)
题目链接 [Scoi2010]序列操作
考验代码能力的一道好题。
思想还是很简单的(直接上线段树),但是比较难写。
#include <bits/stdc++.h> using namespace std; #define REP(i,n) for(int i(0); i < (n); ++i) #define rep(i,a,b) for(int i(a); i <= (b); ++i) #define dec(i,a,b) for(int i(a); i >= (b); --i) #define for_edge(i,x) for(int i = H[x]; i; i = X[i]) #define LL long long #define ULL unsigned long long #define MP make_pair #define PB push_back #define FI first #define SE second #define INF 1 << 30 const int N = 200000 + 10; const int M = 10000 + 10; const int Q = 1000 + 10; const int A = 30 + 1; struct segTree{ int len; int maxn[2], lmax[2], rmax[2], sum[2]; } segtree[N << 2]; int a[N], de_cover[N << 2], de_turn[N << 2]; int n, m, op, x, y; segTree update(segTree x, segTree y){ segTree ans; ans.len = x.len + y.len; rep(i, 0, 1){ ans.sum[i] = x.sum[i] + y.sum[i]; ans.lmax[i] = (x.lmax[i] == x.len ? x.len + y.lmax[i] : x.lmax[i]); ans.rmax[i] = (y.rmax[i] == y.len ? x.rmax[i] + y.len : y.rmax[i]); ans.maxn[i] = max(max(x.maxn[i], y.maxn[i]), max(ans.lmax[i], ans.rmax[i])); ans.maxn[i] = max(ans.maxn[i], x.rmax[i] + y.lmax[i]); } return ans; } void build(int i, int l, int r){ if (l == r){ int z = a[l]; segtree[i].len = segtree[i].sum[z] = segtree[i].lmax[z] = segtree[i].rmax[z] = segtree[i].maxn[z] = 1; segtree[i].sum[z ^ 1] = segtree[i].lmax[z ^ 1] = segtree[i].rmax[z ^ 1] = segtree[i].maxn[z ^ 1] = 0; de_cover[i] = -1, de_turn[i] = 0; return ; } int mid = (l + r) >> 1; build(i << 1, l, mid); build(i << 1 | 1, mid + 1, r); segtree[i] = update(segtree[i << 1], segtree[i << 1 | 1]); de_cover[i] = -1, de_turn[i] = 0; } void paint_cover(int i, int z){ de_cover[i] = z; de_turn[i] = 0; segtree[i].sum[z] = segtree[i].lmax[z] = segtree[i].rmax[z] = segtree[i].maxn[z] = segtree[i].len; segtree[i].sum[z ^ 1] = segtree[i].lmax[z ^ 1] = segtree[i].rmax[z ^ 1] = segtree[i].maxn[z ^ 1] = 0; } void paint_turn(int i, int z){ if (z != -1){ de_cover[i] ^= 1; segtree[i].sum[z] = segtree[i].lmax[z] = segtree[i].rmax[z] = segtree[i].maxn[z] = 0; segtree[i].sum[z ^ 1] = segtree[i].lmax[z ^ 1] = segtree[i].rmax[z ^ 1] = segtree[i].maxn[z ^ 1] = segtree[i].len; } else{ de_turn[i] ^= 1; swap(segtree[i].sum[0], segtree[i].sum[1]); swap(segtree[i].lmax[0], segtree[i].lmax[1]); swap(segtree[i].rmax[0], segtree[i].rmax[1]); swap(segtree[i].maxn[0], segtree[i].maxn[1]); } } void pushdown(int i){ if (de_cover[i] != -1){ paint_cover(i << 1, de_cover[i]); paint_cover(i << 1 | 1, de_cover[i]); de_cover[i] = -1; } if (de_turn[i]){ paint_turn(i << 1, de_cover[i << 1]); paint_turn(i << 1 | 1, de_cover[i << 1 | 1]); de_turn[i] = 0; } } void insert_cover(int i, int l, int r, int x, int y, int z){ if (x <= l && y >= r){ paint_cover(i, z); return ; } pushdown(i); int mid = (l + r) >> 1; if (x <= mid) insert_cover(i << 1, l, mid, x, y, z); if (y > mid) insert_cover(i << 1 | 1, mid + 1, r, x, y, z); segtree[i] = update(segtree[i << 1], segtree[i << 1 | 1]); } void insert_turn(int i, int l, int r, int x, int y){ if (x <= l && y >= r){ paint_turn(i, de_cover[i]); return ; } pushdown(i); int mid = (l + r) >> 1; if (x <= mid) insert_turn(i << 1, l, mid, x, y); if (y > mid) insert_turn(i << 1 | 1, mid + 1, r, x, y); segtree[i] = update(segtree[i << 1], segtree[i << 1 | 1]); } int query_sum(int i, int l, int r, int x, int y){ int sum = 0; if (x <= l && y >= r){ return segtree[i].sum[1];} int mid = (l + r) >> 1; pushdown(i); if (x <= mid) sum += query_sum(i << 1, l, mid, x, y); if (y > mid) sum += query_sum(i << 1 | 1, mid + 1, r, x, y); return sum; } segTree query_con(int i, int l ,int r, int x, int y){ segTree ans1, ans2; bool f1 = false, f2 = false; if (x <= l && y >= r) return segtree[i]; pushdown(i); int mid = (l + r) >> 1; if (x <= mid) ans1 = query_con(i << 1, l, mid, x, y), f1 = true; if (y > mid) ans2 = query_con(i << 1 | 1, mid + 1, r, x, y), f2 = true; if (f1 && f2) return update(ans1, ans2); else return f1 ? ans1 : ans2; } int main(){ scanf("%d%d", &n, &m); rep(i, 1, n) scanf("%d", a + i); build(1, 1, n); while (m--){ scanf("%d%d%d", &op, &x, &y); ++x, ++y; if (op == 0) insert_cover(1, 1, n, x, y, 0); if (op == 1) insert_cover(1, 1, n, x, y, 1); if (op == 2) insert_turn(1, 1, n, x, y); if (op == 3) printf("%d\n", query_sum(1, 1, n, x, y)); if (op == 4) printf("%d\n", query_con(1, 1, n, x, y).maxn[1]); } return 0; }