hdu 3397 Sequence operation(区间合并)

来源:互联网 发布:linux exec fork 编辑:程序博客网 时间:2024/05/16 04:53
题意:首先t表示有几组数据,然后n,m表示有n个数,m组操作,接着给你n个0或1的数字,,最后是操作0 a b表示把区间[a,b]里的数都变成0,1 a b把区间[a,b]里的数都变成1,2 a b表示把区间[a,b]里的1变成0,0变成1,3 a b表示[a,b]输出1的数目,4 a b表示输出最长的连续的1的数目。

区间合并的问题,因为最长的可能的除了可能出现在端点,还有可能出现在区间合并时,两边的连续的加起来。除了这个之外,还要注意,我们设置两个延迟标记,一个用来标记操作0、1,一个用来标记操作2,如果我们在进行操作0、1的更新的时候,如果有遇到操作2的标记,那么没必要往下更新标记2(因为会把操作2覆盖了),但是如果是进行操作2的更新,遇到操作0、1的更新,我们要往下更新。

        因为有涉及到将0变成1,将1变成0的操作,所以我们除了记录端点处连续的1的长度,区间内1的数目,区间内最长的连续的1的数目之外,我们还要记录关于0相同的信息,这样,当有置反操作的时候,我们简单地交换对应的0和1的信息就可以了。

/*代码风格更新后 */#include <iostream>#include <cstdio>#include <cstring>using namespace std;#define LL(x) (x<<1)#define RR(x) (x<<1|1)#define MID(a,b) (a+((b-a)>>1))const int N=100005;struct node{int lft,rht;int lmx_0,rmx_0,mx_0,sum_0;int lmx_1,rmx_1,mx_1,sum_1;int flag_set,flag_rev;int len(){return rht-lft+1;}int mid(){return MID(lft,rht);}void set_0(int a){ lmx_0=rmx_0=mx_0=sum_0=a; }void set_1(int a){ lmx_1=rmx_1=mx_1=sum_1=a; }void init(){set_0(0); set_1(0);flag_rev=0; flag_set=-1;}void fun(int valu){if(valu==0){flag_set=0; flag_rev=0;set_0(len()); set_1(0);}else if(valu==1){flag_set=1; flag_rev=0;set_0(0); set_1(len());}else {swap(lmx_0,lmx_1);  swap(rmx_0,rmx_1);swap(mx_0,mx_1);swap(sum_0,sum_1);flag_rev^=1;}}};int y[N],n,m;struct Segtree{node tree[N*4];void down(int ind){if(tree[ind].flag_set!=-1){tree[LL(ind)].fun(tree[ind].flag_set);tree[RR(ind)].fun(tree[ind].flag_set);tree[ind].flag_set=-1;}if(tree[ind].flag_rev){tree[LL(ind)].fun(2);tree[RR(ind)].fun(2);tree[ind].flag_rev=0;}}void up(node &a,node &b,node &c){a.lmx_0=b.lmx_0;  a.rmx_0=c.rmx_0;  a.lmx_1=b.lmx_1;  a.rmx_1=c.rmx_1;  a.sum_0=b.sum_0+c.sum_0;    a.sum_1=b.sum_1+c.sum_1;  a.mx_0=max(b.rmx_0+c.lmx_0,max(b.mx_0,c.mx_0));  a.mx_1=max(b.rmx_1+c.lmx_1,max(b.mx_1,c.mx_1));  if(b.len()==b.lmx_0) a.lmx_0+=c.lmx_0;  if(b.len()==b.lmx_1) a.lmx_1+=c.lmx_1;  if(c.len()==c.rmx_0) a.rmx_0+=b.rmx_0;  if(c.len()==c.rmx_1) a.rmx_1+=b.rmx_1;  }void build(int lft,int rht,int ind){tree[ind].lft=lft;tree[ind].rht=rht;tree[ind].init();if(lft==rht) {if(y[lft]==1) tree[ind].set_0(0),tree[ind].set_1(1);else tree[ind].set_0(1),tree[ind].set_1(0);}else {int mid=tree[ind].mid();build(lft,mid,LL(ind));build(mid+1,rht,RR(ind));up(tree[ind],tree[LL(ind)],tree[RR(ind)]);}}void updata(int st,int ed,int ind,int valu){int lft=tree[ind].lft,rht=tree[ind].rht;if(st<=lft&&rht<=ed) tree[ind].fun(valu);else {down(ind);int mid=tree[ind].mid();if(st<=mid) updata(st,ed,LL(ind),valu);if(ed> mid) updata(st,ed,RR(ind),valu);up(tree[ind],tree[LL(ind)],tree[RR(ind)]);}}int query(int st,int ed,int ind,int type){int lft=tree[ind].lft,rht=tree[ind].rht;if(st<=lft&&rht<=ed) {if(type==3) return tree[ind].sum_1;else return tree[ind].mx_1;}else {down(ind);int mid=tree[ind].mid(),res;if(ed<=mid) res=query(st,ed,LL(ind),type);else if(st>mid) res=query(st,ed,RR(ind),type);else {int tmp1=query(st,ed,LL(ind),type);int tmp2=query(st,ed,RR(ind),type);if(type==3) res=tmp1+tmp2;else {int tmp3=min(tree[LL(ind)].rmx_1,tree[LL(ind)].rht-st+1);int tmp4=min(tree[RR(ind)].lmx_1,ed-tree[RR(ind)].lft+1);res=max(max(tmp1,tmp2),tmp3+tmp4);}}up(tree[ind],tree[LL(ind)],tree[RR(ind)]);return res;}}}seg;int main(){int t;scanf("%d",&t);while(t--){scanf("%d%d",&n,&m);for(int i=0;i<n;i++) scanf("%d",&y[i]);seg.build(0,n-1,1);for(int i=0;i<m;i++){int a,b,c;scanf("%d%d%d",&a,&b,&c);if(a<=2) seg.updata(b,c,1,a);else printf("%d\n",seg.query(b,c,1,a));}}return 0;}


/*代码风格更新前*/#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int N=100005;int y[N];struct node{    int left,right,co,flag;    int maxl_0,maxr_0,maxl_1,maxr_1;    int sum_0,sum_1,max_1,max_0;    int mid(){return left+(right-left)/2;}    int dis(){return right-left+1;}    void change(int a,int rev)    {        if(a==0)        {            maxl_0=maxr_0=sum_0=max_0=dis();            maxl_1=maxr_1=sum_1=max_1=0;            co=a;   flag=0;        }        else if(a==1)        {            maxl_0=maxr_0=sum_0=max_0=0;            maxl_1=maxr_1=sum_1=max_1=dis();            co=a;   flag=0;        }        if(rev)        {            swap(maxr_1,maxr_0);    swap(maxl_0,maxl_1);            swap(max_0,max_1);      swap(sum_0,sum_1);            flag^=1;        }    }};void unin(node &a,node &b,node &c){    a.maxl_0=b.maxl_0;  a.maxr_0=c.maxr_0;    a.maxl_1=b.maxl_1;  a.maxr_1=c.maxr_1;    a.sum_0=b.sum_0+c.sum_0;    a.sum_1=b.sum_1+c.sum_1;    a.max_0=max(b.maxr_0+c.maxl_0,max(b.max_0,c.max_0));    a.max_1=max(b.maxr_1+c.maxl_1,max(b.max_1,c.max_1));    if(b.dis()==b.maxl_0) a.maxl_0+=c.maxl_0;    if(b.dis()==b.maxl_1) a.maxl_1+=c.maxl_1;    if(c.dis()==c.maxr_0) a.maxr_0+=b.maxr_0;    if(c.dis()==c.maxr_1) a.maxr_1+=b.maxr_1;}struct Segtree{    node tree[N*4];    void build(int left,int right,int r)    {        tree[r].left=left;  tree[r].right=right;        tree[r].maxl_0=tree[r].maxr_0=tree[r].maxl_1=tree[r].maxr_1=0;        tree[r].sum_0=tree[r].sum_1=tree[r].max_0=tree[r].max_1=0;        tree[r].flag=0;     tree[r].co=-1;        if(left==right)        {            tree[r].change(y[left],0);        }        else        {            int mid=tree[r].mid();            build(left,mid,r*2);    build(mid+1,right,r*2+1);            unin(tree[r],tree[r*2],tree[r*2+1]);        }    }    void updata(int be,int end,int r,int co)    {        if(be<=tree[r].left&&tree[r].right<=end)        {            if(co==0||co==1) tree[r].change(co,0);            else tree[r].change(-1,1);        }        else        {            if(tree[r].co!=-1||tree[r].flag)            {                tree[r*2].change(tree[r].co,tree[r].flag);                tree[r*2+1].change(tree[r].co,tree[r].flag);                tree[r].co=-1;  tree[r].flag=0;            }            int mid=tree[r].mid();            if(be<=mid) updata(be,end,r*2,co);            if(end>mid) updata(be,end,r*2+1,co);            unin(tree[r],tree[r*2],tree[r*2+1]);        }    }    int query(int be,int end,int r,int co)    {        if(be<=tree[r].left&&tree[r].right<=end)        {            if(co==3) return tree[r].sum_1;            else return tree[r].max_1;        }        else        {            if(tree[r].co!=-1||tree[r].flag)            {                tree[r*2].change(tree[r].co,tree[r].flag);                tree[r*2+1].change(tree[r].co,tree[r].flag);                tree[r].co=-1;  tree[r].flag=0;            }            int mid=tree[r].mid();            if(end<=mid) return query(be,end,r*2,co);            else if(be>mid) return query(be,end,r*2+1,co);            else            {                int max1=query(be,end,r*2,co);                int max2=query(be,end,r*2+1,co);                if(co==3) return max1+max2;                int max3=min(tree[r*2].right-be+1,tree[r*2].maxr_1)+min(end-tree[r*2+1].left+1,tree[r*2+1].maxl_1);                return max(max(max1,max2),max3);            }        }    }}seg;int main(){    int t;    scanf("%d",&t);    while(t--)    {        int n,m;        scanf("%d%d",&n,&m);        for(int i=0;i<n;i++) scanf("%d",&y[i]);        seg.build(0,n-1,1);        for(int i=0;i<m;i++)        {            int a,b,c;            scanf("%d%d%d",&a,&b,&c);            if(a==0||a==1||a==2) seg.updata(b,c,1,a);            else printf("%d\n",seg.query(b,c,1,a));            //for(int j=0;j<n;j++) printf("%d ",seg.query(j,j,1,3)); puts("");        }    }    return 0;}




原创粉丝点击