hdu 3397 Sequence operation 线段树

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

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

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

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

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

代码有点长,但是不难

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|1
int 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;
}
posted @ 2012-04-20 16:35  Because Of You  Views(457)  Comments(0Edit  收藏  举报