hdu3397

来源:互联网 发布:日本女孩知乎 编辑:程序博客网 时间:2024/05/21 14:53

此题中维护操作略多,先说下思路

有两种更新操作set和update分别为设置[a,b]为0或1和求[a,b]反;

1.每次set操作时看是否是[a,b]覆盖区间,不是则查看是否此节点有set(1)或set(0)的标志,如果有的话,需要

把这个set标志pushdown到L(t),R(t),然后再把[a,b]的取反标志f,pushdown下去,然后递归查找左右子树。

如果【a,b]是覆盖区间,那么直接设置set标志,并把取反标志设0,(因为此时下边区间是否取反已经无所谓了)

2.每次update取反时差不多,需要把有set标志的先pushdown然后pushdown取反标志。

因为一个节点如果同时有两个标志时,一定表示这个节点先进行了set然后才取反,所以pushdown的时候先push set标志然后是取反标志。

假设是标志设置顺序是先取反,那么后来的set标志时后吧f清零(每set一个覆盖区间,相应区间的f=0)所以只可能是先set,再取反

#include<iostream>#include<stdio.h>#include<string.h>#include<algorithm>#include<cmath>#define L(x) (x<<1)#define R(x) (x<<1|1)#define MAX 100010using namespace std;void Swap(int t);void upwb(int t);void uplen(int t);void setdown(int t);void setdowncover(int t);void build(int t,int l, int r);void set(int t,int l,int r,int val);int querysum(int t,int l,int r);void update(int t,int l,int r);int queryblen(int t,int l,int r);struct node{    int l,r;    int wr,wl,br,bl;    int wlen,blen;    int cover;    int sum;    bool f;}a[MAX*3];int number[MAX];int main(){    int t,m,n,i,l,r,p;    scanf("%d",&t);    while(t--)    {        scanf("%d%d",&n,&m);        for(i=0;i<n;i++)        {            scanf("%d",&number[i]);        }        build(1,0,n-1);        for(i=0;i<m;i++)        {            scanf("%d%d%d",&p,&l,&r);            switch(p)            {                case 0:;                case 1:set(1,l,r,p);break;                case 2:update(1,l,r);break;                case 3:printf("%d\n",querysum(1,l,r));break;                case 4:printf("%d\n",queryblen(1,l,r));            }        }    }}void Swap(int t){    swap(a[t].wlen,a[t].blen);    swap(a[t].wl,a[t].bl);    swap(a[t].wr,a[t].br);    a[t].sum=a[t].r-a[t].l+1-a[t].sum;}void upwb(int t){    int ll=a[L(t)].r-a[L(t)].l+1;    a[t].wl=a[L(t)].wl+(a[L(t)].wl==ll?a[R(t)].wl:0);    a[t].bl=a[L(t)].bl+(a[L(t)].bl==ll?a[R(t)].bl:0);    ll=a[R(t)].r-a[R(t)].l+1;    a[t].wr=a[R(t)].wr+(a[R(t)].wr==ll?a[L(t)].wr:0);    a[t].br=a[R(t)].br+(a[R(t)].br==ll?a[L(t)].br:0);    a[t].wlen=max(max(a[L(t)].wlen,a[R(t)].wlen),a[L(t)].wr+a[R(t)].wl);    a[t].blen=max(max(a[L(t)].blen,a[R(t)].blen),a[L(t)].br+a[R(t)].bl);}void uplen(int t){    if(a[t].cover>0)    {        a[t].sum=a[t].r-a[t].l+1;        a[t].wlen=a[t].wl=a[t].wr=0;        a[t].blen=a[t].bl=a[t].br=a[t].sum;        return;    }    if(a[t].cover==0)    {        a[t].sum=0;        a[t].wlen=a[t].r-a[t].l+1;        a[t].wr=a[t].wl=a[t].wlen;        a[t].blen=a[t].br=a[t].bl=0;        return ;    }    a[t].sum=a[L(t)].sum+a[R(t)].sum;    upwb(t);}void setdown(int t){    if(a[t].f)    {        a[L(t)].f=!a[L(t)].f;        a[R(t)].f=!a[R(t)].f;        a[t].f=!a[t].f;        Swap(L(t));        Swap(R(t));    }}void setdowncover(int t){    a[L(t)].cover=a[t].cover;    a[R(t)].cover=a[t].cover;    a[t].cover=-1;    uplen(L(t));    uplen(R(t));    a[L(t)].f=0;    a[R(t)].f=0;}void build(int t,int l, int r){    a[t].l=l;    a[t].r=r;    a[t].f=0;    a[t].cover=-1;    if(l==r)    {        a[t].blen=number[l];        a[t].wlen=1-a[t].blen;        a[t].wr=a[t].wl=a[t].wlen;        a[t].bl=a[t].br=a[t].blen;        a[t].sum=number[l];        return ;    }    int mid=(l+r)>>1;    build(L(t),l,mid);    build(R(t),mid+1,r);    uplen(t);}void set(int t,int l,int r,int val){    if(l<=a[t].l&&a[t].r<=r)    {        a[t].cover=val;        a[t].f=0;        uplen(t);        return ;    }    if(a[t].cover!=-1)    {        setdowncover(t);        a[L(t)].f=0;        a[R(t)].f=0;    }      setdown(t);    int mid=(a[t].l+a[t].r)>>1;    if(l<=mid)      set(L(t),l,r,val);    if(r>mid)      set(R(t),l,r,val);    uplen(t);}int querysum(int t,int l,int r){    if(l<=a[t].l&&a[t].r<=r)    {        return a[t].sum;    }    if(a[t].cover!=-1)    {        setdowncover(t);    }      setdown(t);    int mid=(a[t].l+a[t].r)>>1;    int ans=0;    if (l<=mid)      ans+=querysum(L(t),l,r);    if(r>mid)      ans+=querysum(R(t),l,r);    uplen(t);    return ans;}void update(int t,int l,int r){    if(l<=a[t].l&&a[t].r<=r)    {        a[t].f=!a[t].f;        Swap(t);        return ;    }    if(a[t].cover!=-1)    {        setdowncover(t);    }        setdown(t);    int mid=(a[t].l+a[t].r)>>1;    if(l<=mid)      update(L(t),l,r);    if(r>mid)      update(R(t),l,r);    uplen(t);}int queryblen(int t,int l,int r){    if(l<=a[t].l&&a[t].r<=r)    {        return a[t].blen;    }    if(a[t].cover!=-1)    {        setdowncover(t);    }      setdown(t);    int mid=(a[t].l+a[t].r)>>1;    int ans=0;    int p=0;    int q=0;    if(l<=mid)    {        ans=max(ans,queryblen(L(t),l,r));        if(r>=a[L(t)].r)          p=min(a[L(t)].br,a[L(t)].r-l+1);    }    if(r>mid)    {        ans=max(ans,queryblen(R(t),l,r));        if(l<=a[R(t)].l)          q=min(a[R(t)].bl,r-a[R(t)].l+1);    }    ans=max(ans,p+q);    uplen(t);    return ans;}


原创粉丝点击