HDU3397 Sequence operation 区间修改,区间异或,区间合并,线段树经典题

来源:互联网 发布:ubuntu dns配置文件 编辑:程序博客网 时间:2024/06/05 11:40
分别记录下0和1的连续段,异或就是把01值交换,不难,想清楚再敲
#include <stdio.h>#include <string.h>#include <algorithm>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define ls (rt<<1)#define rs (rt<<1|1)const int M = 100001;int n,d;int Xor[M<<2];int cover[M<<2];int lpa[M<<2][2],rpa[M<<2][2],mpa[M<<2][2],num[M<<2][2];int L,R,op;int max(int a, int b) { return a>b?a:b; }int min(int a, int b) { return a<b?a:b; }void swap(int &a, int &b) { int temp = a; a = b; b = temp; }void Or(int rt){if(cover[rt] != -1){cover[rt] ^= 1;}else{Xor[rt] ^= 1;}}void SWAP(int rt){swap(lpa[rt][0], lpa[rt][1]);swap(rpa[rt][0], rpa[rt][1]);swap(mpa[rt][0], mpa[rt][1]);swap(num[rt][0], num[rt][1]);}void pushup(int m, int len, int rt){for(int i=0; i<2; i++){lpa[rt][i] = lpa[ls][i];rpa[rt][i] = rpa[rs][i];if(lpa[rt][i] == len-(len>>1)) lpa[rt][i] += lpa[rs][i];if(rpa[rt][i] == (len>>1)) rpa[rt][i] += rpa[ls][i];mpa[rt][i] = rpa[ls][i] + lpa[rs][i];mpa[rt][i] = max(mpa[rt][i], max(mpa[ls][i], mpa[rs][i]));mpa[rt][i] = max(mpa[rt][i], max(lpa[rt][i], rpa[rt][i]));num[rt][i] = num[ls][i] + num[rs][i];}if(cover[ls]!=-1 && cover[ls]==cover[rs]) cover[rt] = cover[ls];else cover[rt] = -1;}void pushdown(int m, int len, int rt){if(cover[rt] != -1){d = cover[rt];lpa[ls][d] = rpa[ls][d] = mpa[ls][d] = num[ls][d] = len-(len>>1);lpa[ls][!d] = rpa[ls][!d] = mpa[ls][!d] = num[ls][!d] = 0;cover[ls] = cover[rs] = d;Xor[ls] = Xor[rs] = 0;lpa[rs][d] = rpa[rs][d] = mpa[rs][d] = num[rs][d] = (len>>1);lpa[rs][!d] = rpa[rs][!d] = mpa[rs][!d] = num[rs][!d] = 0;}else if(Xor[rt]){Or(ls);SWAP(ls);Or(rs);SWAP(rs);}cover[rt] = -1;Xor[rt] = 0;}void build(int l, int r, int rt){Xor[rt] = 0;if(l == r){scanf("%d", &d);cover[rt] = d;lpa[rt][d] = rpa[rt][d] = mpa[rt][d] = num[rt][d] = 1;lpa[rt][!d] = rpa[rt][!d] = mpa[rt][!d] = num[rt][!d] = 0;}else{int m = (l+r)>>1;build(lson);build(rson);pushup(m,r-l+1,rt);}}void update(int l, int r, int rt){if(L<=l && r<=R){if(op <= 1){Xor[rt] = 0;cover[rt] = op;lpa[rt][op] = rpa[rt][op] = mpa[rt][op] = num[rt][op] = r-l+1;lpa[rt][!op] = rpa[rt][!op] = mpa[rt][!op] = num[rt][!op] = 0;}else{SWAP(rt);Or(rt);}}else{int m = (l+r)>>1;pushdown(m,r-l+1,rt);if(L <= m) update(lson);if(m <  R) update(rson);pushup(m,r-l+1,rt);}}int query(int l, int r, int rt){if(L<=l && r<=R){if(op == 3) return num[rt][1];else return mpa[rt][1];}else{int m = (l+r)>>1;pushdown(m,r-l+1,rt);if(op == 3){int ans = 0;if(L <= m) ans = query(lson);if(m <  R) ans += query(rson);return ans;}else{int ans = min(rpa[ls][1],m-L+1) + min(lpa[rs][1],R-m);if(L <= m) ans = max(ans, query(lson));if(m <  R) ans = max(ans, query(rson));return ans;}}}int main(){int m;int cas;scanf("%d", &cas);while(cas--){scanf("%d%d", &n, &m);build(0,n-1,1);while(m--){scanf("%d%d%d", &op, &L, &R);if(op >= 3) printf("%d\n", query(0,n-1,1));else update(0,n-1,1);}}return 0;}

区间修改,区间异或,区间合并,线段树经典题