HDU 3397 Sequence operation

来源:互联网 发布:聚划算计入淘宝搜索吗 编辑:程序博客网 时间:2024/05/18 03:49

【题意】操作区间上只有0和1,操作有两个,第一个是区间染色,第二个是区间反转(01变换).询问也用两个,一个是询问区间内1个个数,二是询问区间内最长的连续的1的个数。

【解题方法】典型的线段树区间合并。难点是有2种区间操作,处理好这两种操作的关系,这道题也就没有难点了。我们观察可以发现,覆盖的优先级高于反转。无论这个区间怎样反转,只要来一次覆盖,所有的反转都将会失效。所以,在pushdown的时候,如果有染色的话,我们直接把作友儿子的反转标记置0。而且在一个节点上,反转和覆盖不会同时存在,即使某个区间刚被覆盖,我们对他进行反转的时候,我们直接反转覆盖值即可。这里,标记反转有个技巧,反转2次就是没反转,我们用异或1来代表一次反转操作。

【AC 代码】

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int maxn=100010;struct node{    int l,r,len;    int l0,r0,s0;    int l1,r1,s1;    int sum;//区间1的个数    int mark;//区间反转标记    int cover;//区间覆盖标记}Tree[maxn<<2];void pushup(int rt){    Tree[rt].l1=Tree[rt*2].l1;    Tree[rt].r1=Tree[rt*2+1].r1;    if(Tree[rt].l1==Tree[rt*2].len) Tree[rt].l1=Tree[rt*2].l1+Tree[rt*2+1].l1;    if(Tree[rt].r1==Tree[rt*2+1].len) Tree[rt].r1=Tree[rt*2].r1+Tree[rt*2+1].len;    Tree[rt].s1=max(max(Tree[rt*2].s1,Tree[rt*2+1].s1),Tree[rt*2].r1+Tree[rt*2+1].l1);    Tree[rt].l0=Tree[rt*2].l0;    Tree[rt].r0=Tree[rt*2+1].r0;    if(Tree[rt].l0==Tree[rt*2].len) Tree[rt].l0=Tree[rt*2].len+Tree[rt*2+1].l0;    if(Tree[rt].r0==Tree[rt*2+1].len) Tree[rt].r0=Tree[rt*2].r0+Tree[rt*2+1].len;    Tree[rt].s0=max(max(Tree[rt*2].s0,Tree[rt*2+1].s0),Tree[rt*2].r0+Tree[rt*2+1].l0);    Tree[rt].sum=Tree[rt*2].sum+Tree[rt*2+1].sum;}void change(int rt,int v)//对节点的信息进行修改{    if(v==0||v==1){//覆盖处理        Tree[rt].l1=Tree[rt].r1=Tree[rt].s1=v?Tree[rt].len:0;        Tree[rt].l0=Tree[rt].r0=Tree[rt].s0=v?0:Tree[rt].len;        Tree[rt].sum=v?Tree[rt].len:0;        Tree[rt].cover=v;    }    else{//XOR        swap(Tree[rt].l0,Tree[rt].l1);        swap(Tree[rt].r0,Tree[rt].r1);        swap(Tree[rt].s0,Tree[rt].s1);        Tree[rt].sum=Tree[rt].len-Tree[rt].sum;        Tree[rt].mark^=1;        if(Tree[rt].cover!=-1){            Tree[rt].cover=1-Tree[rt].cover;        }    }}void pushdown(int rt){    if(Tree[rt].mark){        change(rt*2,2);        change(rt*2+1,2);        Tree[rt].mark=0;    }    if(Tree[rt].cover!=-1){        change(rt*2,Tree[rt].cover);        change(rt*2+1,Tree[rt].cover);        Tree[rt].cover=-1;    }}void Build(int l,int r,int rt){    Tree[rt].l=l,Tree[rt].r=r,Tree[rt].len=r-l+1;    Tree[rt].mark=0,Tree[rt].cover=-1;    if(l==r){        int x;        scanf("%d",&x);        Tree[rt].l0=Tree[rt].r0=Tree[rt].s0=x?0:1;        Tree[rt].l1=Tree[rt].r1=Tree[rt].s1=x?1:0;        Tree[rt].sum=x?1:0;        return ;    }    int mid=(l+r)/2;    Build(l,mid,rt*2);    Build(mid+1,r,rt*2+1);    pushup(rt);}void update(int L,int R,int kind,int rt){    if(L==Tree[rt].l&&Tree[rt].r==R){        change(rt,kind);        return ;    }    pushdown(rt);    int mid=(Tree[rt].l+Tree[rt].r)/2;    if(R<=mid) update(L,R,kind,rt*2);    else if(L>mid) update(L,R,kind,rt*2+1);    else{        update(L,mid,kind,rt*2);        update(mid+1,R,kind,rt*2+1);    }    pushup(rt);}int queryans(int L,int R,int kind,int rt){    if(L==Tree[rt].l&&Tree[rt].r==R){        if(kind==3) return Tree[rt].sum;        else return Tree[rt].s1;    }    pushdown(rt);    int mid=(Tree[rt].l+Tree[rt].r)/2;    if(R<=mid) return queryans(L,R,kind,rt*2);    else if(L>mid) return queryans(L,R,kind,rt*2+1);    else{        int ans1,ans2;        ans1=queryans(L,mid,kind,rt*2);        ans2=queryans(mid+1,R,kind,rt*2+1);        if(kind==3) return ans1+ans2;        else return max(max(ans1,ans2),min(mid-L+1,Tree[rt*2].r1)+min(R-mid,Tree[rt*2+1].l1));    }}int main(){    int T,n,q;    scanf("%d",&T);    while(T--)    {        scanf("%d%d",&n,&q);        Build(1,n,1);        //puts("success");        int op,l,r;        while(q--){            scanf("%d%d%d",&op,&l,&r);            l++,r++;            if(op<=2) update(l,r,op,1);            else if(op>=3){                printf("%d\n",queryans(l,r,op,1));            }        }    }}


0 0
原创粉丝点击