hdu 3397 Sequence operation 线段树

来源:互联网 发布:自学unity3d能找工作吗 编辑:程序博客网 时间:2024/05/16 18:02

一看思路就比较清晰的线段树

5个操作,3个修改区间,2个询问

flag值 -1 , 1 , 0

-1表示,左孩子和右孩子的值不等

1 表示,左孩子和右孩子的值都等于1

0表示,左孩子和右孩子的值都等于0

这样就可以用flag值 进行 懒标记了,更新到 段。。


我只标记了1,的相关信息,

还可以多标记下0,的相关信息,这样更新时,只需将1和0的参数交换一下。。


#include<stdio.h>#include<string.h>#include<algorithm>#include<iostream>#include<math.h>using namespace std;#define inf 0x3f3f3f3f#define N 100010struct node{int flag,sum;int l,r,la,lb,ll;int a,b,len;}tree[4*N];int p[N];void gengxin(int id){if(tree[id].flag==0){tree[id].flag=0;tree[id].sum=tree[id].a=tree[id].b=tree[id].la=tree[id].lb=0;tree[id].ll=0;}else if(tree[id].flag==1){tree[id].flag=1;tree[id].a=tree[id].b=1;tree[id].sum=tree[id].la=tree[id].lb=tree[id].ll=tree[id].len;}}void build(int id,int x,int y){tree[id].l=x;tree[id].r=y;tree[id].len=y-x+1;tree[id].a=p[x];tree[id].b=p[y];tree[id].flag=-1;if(x==y){tree[id].flag=p[x];tree[id].la=p[x];tree[id].lb=tree[id].ll=tree[id].sum=p[x];return ;}int mid=(x+y)>>1;build(id<<1,x,mid);build((id<<1)+1,mid+1,y);if(tree[id<<1].flag==tree[(id<<1)+1].flag && tree[id<<1].flag!=-1)tree[id].flag=tree[id<<1].flag;if(tree[id].flag!=-1){gengxin(id);}else{tree[id].sum=tree[id<<1].sum+tree[(id<<1)+1].sum;if(tree[id<<1].la==tree[id<<1].len && tree[(id<<1)+1].a==1)tree[id].la=tree[id<<1].len+tree[(id<<1)+1].la;else tree[id].la=tree[id<<1].la;if(tree[(id<<1)+1].lb==tree[(id<<1)+1].len && tree[id<<1].b==1)tree[id].lb=tree[(id<<1)+1].len+tree[id<<1].lb;elsetree[id].lb=tree[(id<<1)+1].lb;tree[id].ll=max(tree[id<<1].ll,tree[(id<<1)+1].ll);if(tree[id<<1].b==1 && tree[(id<<1)+1].a==1)tree[id].ll=max(tree[id].ll,tree[id<<1].lb+tree[(id<<1)+1].la);}}void change(int id,int x,int y,int f){if(tree[id].l==x && tree[id].r==y && (!(f==2 && tree[id].flag==-1))){if(f==0 || (f==2&&tree[id].flag==1)){tree[id].flag=0;tree[id].sum=tree[id].a=tree[id].b=tree[id].la=tree[id].lb=0;tree[id].ll=0;}else if(f==1 || (f==2&&tree[id].flag==0)){tree[id].flag=1;tree[id].a=tree[id].b=1;tree[id].sum=tree[id].la=tree[id].lb=tree[id].ll=tree[id].len;}return ;}int mid=(tree[id<<1].l+tree[(id<<1)+1].r)>>1;if(tree[id].flag!=-1){tree[id<<1].flag=tree[(id<<1)+1].flag=tree[id].flag;tree[id].flag=-1;gengxin(id<<1);gengxin((id<<1)+1);}if(y<=mid) change(id<<1,x,y,f);else if(x>=mid+1) change((id<<1)+1,x,y,f);else{change(id<<1,x,mid,f);change((id<<1)+1,mid+1,y,f);}tree[id].a=tree[id<<1].a;tree[id].b=tree[(id<<1)+1].b; //更新段的 左值,右值if(tree[id<<1].flag==tree[(id<<1)+1].flag && tree[id<<1].flag!=-1)tree[id].flag=tree[id<<1].flag;  //更新flag值if(tree[id].flag!=-1){gengxin(id);}else{tree[id].sum=tree[id<<1].sum+tree[(id<<1)+1].sum; //更新区间的和if(tree[id<<1].la==tree[id<<1].len && tree[(id<<1)+1].a==1)tree[id].la=tree[id<<1].len+tree[(id<<1)+1].la;else tree[id].la=tree[id<<1].la;if(tree[(id<<1)+1].lb==tree[(id<<1)+1].len && tree[id<<1].b==1)tree[id].lb=tree[(id<<1)+1].len+tree[id<<1].lb;elsetree[id].lb=tree[(id<<1)+1].lb;//更新左右段 连续的长tree[id].ll=max(tree[id<<1].ll,tree[(id<<1)+1].ll);if(tree[id<<1].b==1 && tree[(id<<1)+1].a==1)tree[id].ll=max(tree[id].ll,tree[id<<1].lb+tree[(id<<1)+1].la);//更新每段最长的值}}int querysum(int id,int x,int y){if(tree[id].l==x && tree[id].r==y)return tree[id].sum;//只更新到段if(tree[id].flag!=-1){  //查询下一层,需要更新下一层tree[id<<1].flag=tree[(id<<1)+1].flag=tree[id].flag;tree[id].flag=-1;gengxin(id<<1);gengxin((id<<1)+1);}int mid=(tree[id<<1].l+tree[(id<<1)+1].r)>>1;if(y<=mid) return querysum(id<<1,x,y);else if(x>=mid+1) return querysum((id<<1)+1,x,y);else{return querysum(id<<1,x,mid)+querysum((id<<1)+1,mid+1,y);}}int queryll(int id,int x,int y){if(tree[id].l==x && tree[id].r==y)return tree[id].ll;//只更新到段if(tree[id].flag!=-1){ //查询下一层,需要更新下一层tree[id<<1].flag=tree[(id<<1)+1].flag=tree[id].flag;tree[id].flag=-1;gengxin(id<<1);gengxin((id<<1)+1);}int mid=(tree[id<<1].l+tree[(id<<1)+1].r)>>1;if(y<=mid) return queryll(id<<1,x,y);else if(x>=mid+1) return queryll((id<<1)+1,x,y);else{int t1=queryll(id<<1,x,mid);int t2=queryll((id<<1)+1,mid+1,y);int mx=max(t1,t2);if(tree[id<<1].b==tree[(id<<1)+1].a && tree[id<<1].b==1 )return max(mx,min(tree[id<<1].lb,mid-x+1)+min(tree[(id<<1)+1].la,y-mid)); //查询段长,一定要注意,不要越界elsereturn mx;}}int main(){int t;cin>>t;while(t--){int n,m;cin>>n>>m;int i,j,k;int a,b,c;for(i=1;i<=n;i++)scanf("%d",&p[i]);build(1,1,n);while(m--){scanf("%d%d%d",&a,&b,&c);b++,c++;if(a==0 || a==1 || a==2)change(1,b,c,a);else if(a==3)printf("%d\n",querysum(1,b,c));else if(a==4)printf("%d\n",queryll(1,b,c));}}}


0 0
原创粉丝点击