hdu 3397 Sequence operation 线段树

来源:互联网 发布:java 轮询查询数据库 编辑:程序博客网 时间:2024/05/16 12:48

这道题关键是有两个延迟标记

当区间被完全覆盖时,要撤销抑或操作

所以每次先判断当前区间有没有被完全覆盖

有的话就直接改变相应的值,没有的话在判断有无异或标记

主要是这个地方要注意,其他地方都和另外一道题一样

代码有点长,但是不难

View Code
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn = 100010;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1int num0[maxn<<2],num1[maxn<<2];int lb0[maxn<<2],lb1[maxn<<2];int rb0[maxn<<2],rb1[maxn<<2];int mx1[maxn<<2],mx0[maxn<<2];int col[maxn<<2];int xor[maxn<<2];int num;int max(int a,int b){    return a>b?a:b;}int min(int a,int b){    return a<b?a:b;}void pushup(int rt,int m){    lb0[rt]=lb0[rt<<1];rb0[rt]=rb0[rt<<1|1];    if(lb0[rt]==m-(m>>1)) lb0[rt]+=lb0[rt<<1|1];    if(rb0[rt]==(m>>1))  rb0[rt]+=rb0[rt<<1];        lb1[rt]=lb1[rt<<1];rb1[rt]=rb1[rt<<1|1];    if(lb1[rt]==m-(m>>1)) lb1[rt]+=lb1[rt<<1|1];    if(rb1[rt]==(m>>1))  rb1[rt]+=rb1[rt<<1];        num0[rt]=num0[rt<<1]+num0[rt<<1|1];    num1[rt]=num1[rt<<1]+num1[rt<<1|1];        mx1[rt]=max(mx1[rt<<1],mx1[rt<<1|1]);    mx1[rt]=max(mx1[rt],rb1[rt<<1]+lb1[rt<<1|1]);        mx0[rt]=max(mx0[rt<<1],mx0[rt<<1|1]);    mx0[rt]=max(mx0[rt],rb0[rt<<1]+lb0[rt<<1|1]);}void build(int l,int r,int rt){    col[rt]=-1; xor[rt]=0;    if(l==r){        scanf("%d",&num);        num0[rt]=lb0[rt]=rb0[rt]=mx0[rt]=(num?0:1);        num1[rt]=lb1[rt]=rb1[rt]=mx1[rt]=(num?1:0);        return ;    }    int m=(l+r)>>1;    build(lson);    build(rson);    pushup(rt,r-l+1);}void init(int rt,int m,int cmd){   lb0[rt]=rb0[rt]=mx0[rt]=num0[rt]=m*(1-cmd);   lb1[rt]=rb1[rt]=mx1[rt]=num1[rt]=m*cmd;}void change(int rt){    swap(lb0[rt],lb1[rt]);    swap(rb0[rt],rb1[rt]);    swap(mx0[rt],mx1[rt]);    swap(num0[rt],num1[rt]);}void pushdown(int rt,int m){    if(col[rt]!=-1){         col[rt<<1]=col[rt<<1|1]=col[rt];         xor[rt<<1]=xor[rt<<1|1]=0;         init(rt<<1,m-(m>>1),col[rt]);         init(rt<<1|1,(m>>1),col[rt]);         col[rt]=-1;    }    else if(xor[rt]){        if(col[rt<<1]!=-1){            col[rt<<1]^=1;            init(rt<<1,m-(m>>1),col[rt<<1]);        }        else {            xor[rt<<1]^=1;            change(rt<<1);        }        if(col[rt<<1|1]!=-1){            col[rt<<1|1]^=1;            init(rt<<1|1,(m>>1),col[rt<<1|1]);        }        else {            xor[rt<<1|1]^=1;            change(rt<<1|1);        }        xor[rt]=0;    }}void update(int L,int R,int cmd,int l,int r,int rt){    if(L<=l&&r<=R){        if(cmd<=1){            xor[rt]=0;//取消异或标记            col[rt]=cmd;//真个区间被完全覆盖为cmd            init(rt,r-l+1,cmd);        }        else {            if(col[rt]!=-1){//被完全覆盖,全是0或者全是1,相当于取反                col[rt]^=1;                init(rt,r-l+1,col[rt]);            }            else {                xor[rt]^=1;                change(rt);            }        }        return ;    }    pushdown(rt,r-l+1);    int m=(l+r)>>1;    if(L<=m) update(L,R,cmd,lson);    if(R>m) update(L,R,cmd,rson);    pushup(rt,r-l+1);}int query1(int L,int R,int l,int r,int rt){    if(L<=l&&r<=R)  return num1[rt];    pushdown(rt,r-l+1);    int m=(l+r)>>1;    int ans=0;    if(L<=m) ans+=query1(L,R,lson);    if(R>m) ans+=query1(L,R,rson);    return ans;}int  query2(int L,int R,int l,int r,int rt){    if(L<=l&&r<=R) {        return mx1[rt];    }    pushdown(rt,r-l+1);    int m=(l+r)>>1;    if(R<=m) return query2(L,R,lson);    if(L>m) return query2(L,R,rson);    int a=query2(L,R,lson);    int b=query2(L,R,rson);    a=a>b?a:b;    b=min(m-L+1,rb1[rt<<1])+min(R-m,lb1[rt<<1|1]);    return a>b?a:b;}int main(){    int t,n,m,op,a,b;    scanf("%d",&t);    while(t--){        scanf("%d%d",&n,&m);        build(0,n-1,1);        while(m--){            scanf("%d%d%d",&op,&a,&b);            if(op<=2) update(a,b,op,0,n-1,1);            else {                if(op==3) printf("%d\n",query1(a,b,0,n-1,1));                else printf("%d\n",query2(a,b,0,n-1,1));            }        }    }    return 0;}
原创粉丝点击