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
- 线段树 HDU 3397 Sequence operation
- HDU 3397 Sequence operation (线段树)
- HDU 3397 Sequence operation (线段树)
- HDU 3397 Sequence operation (线段树)
- hdu 3397 Sequence operation 线段树
- hdu 3397 Sequence operation 线段树
- HDU 3397 Sequence operation(线段树)
- HDU 3397 Sequence operation 线段树
- hdu 3397 Sequence operation 线段树
- hdu 3397 Sequence operation(线段树)
- HDU 3397 Sequence operation(线段树)
- HDU - 3397 Sequence operation(线段树)
- hdu 3397 Sequence operation(线段树)
- HDU 3397 Sequence operation 线段树(区间合并)
- hdu 3397 Sequence operation(线段树的各种操作)
- hdu 3397 线段树前后缀blahblah Sequence operation
- hdu 3397 Sequence operation(很有意思的线段树题)
- hdu 3397 Sequence operation(线段树,lazy,区间合并)
- 网页中集成SAP的WebGUI,可以指定用户名、密码、事务码
- c# 数据导入到EXCEL的方法
- spring .xml中bean下的property属性
- NYOJ420 p次方求和 快速幂取模
- github常用指令
- hdu 3397 Sequence operation 线段树
- 我是干嘛的
- 数组右移
- php oauth v1.0 详解客户端和服务端流程与实现
- struts2拦截器实现Action调用后逻辑处理
- ldconfig
- 解决 VMWARE 无法连接USB 设备
- POJ - 1182 食物链(并查集)
- 开始细细品味