传送门:http://oj.cnuschool.org.cn/oj/home/problem.htm?problemID=986
WZJ的数据结构(八) |
难度级别:E; 运行时间限制:3000ms; 运行空间限制:51200KB; 代码长度限制:2000000B |
试题描述
|
给你一个N个节点的森林,从1到N编号,每个点有权值。请你设计一个数据结构,进行以下两种操作: 1.修改:给你a、b、c,将a到b路径上所有点的权值改成c。 2.增加:给你a、b、c,将a到b路径上所有点的权值增加c。 3.询问:给你a、b,输出从a到b路径上经过所有点权值的最大值、最小值与权值和。 |
输入
|
第一行为一个正整数N。
接下来N-1行为每一条边,每行2个正整数a,b,表示有一条从a到b的边(从1开始编号)。 第N+1行为n个正整数Ai,表示每个点的开始权值。 第N+2行为一个正整数Q,表示Q次操作。 接下来Q行为每一次询问,每行3或4个正整数(t)、a、b、c。 若t=0表示修改,t=1表示增加,t=2表示查询。 |
输出
|
对于每一次询问,输出结果。
|
输入示例
|
5 1 2 1 3 2 5 5 4 1 3 2 3 5 5 2 1 5 2 3 4 0 3 5 2 1 1 4 1 2 3 4 |
输出示例
|
5 1 9 5 1 14 4 2 15 |
其他说明
|
1<=N<=100000
1<=Q<=100000 1<=Ai<=1000 1<=a,b<=N 1<=c<=1000 |
题解:树链剖分直接套上1010好了。。。
更新:指针的线段树+邻接表:
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<queue> 6 #include<cstring> 7 #define PAU putchar(' ') 8 #define ENT putchar('\n') 9 #define CH for(int d=0;d<=1;d++) if(ch[d]) 10 #define lson x->ch[0],L,M 11 #define rson x->ch[1],M+1,R 12 using namespace std; 13 const int maxn=100000+10,inf=-1u>>1; 14 struct node{ 15 node*ch[2];int mx,mi,sm,set,add,siz; 16 node(){set=inf;add=0;} 17 void init(int t){mi=mx=sm=t;return;} 18 void addt(int tag){ 19 mi+=tag;mx+=tag;sm+=tag*siz;add+=tag;return; 20 } 21 void sett(int tag){ 22 add=0;mi=mx=set=tag;sm=siz*tag;return; 23 } 24 void update(){ 25 mi=inf;mx=-inf;sm=0; 26 CH{mi=min(mi,ch[d]->mi);mx=max(mx,ch[d]->mx);sm+=ch[d]->sm;} 27 return; 28 } 29 void down(){ 30 if(set!=inf){CH{ch[d]->sett(set);}set=inf;} 31 if(add){CH{ch[d]->addt(add);}add=0;} 32 return; 33 } 34 }seg[maxn<<1],*nodecnt=seg,*root; 35 int A[maxn],n,Q,ql,qr,cv,tp,_mi,_mx,_sm; 36 void build(node*&x,int L,int R){ 37 x=nodecnt++; 38 if(L==R) x->init(A[L]); 39 else{ 40 int M=L+R>>1; 41 build(lson);build(rson); 42 x->update(); 43 } x->siz=R-L+1;return; 44 } 45 void update(node*&x,int L,int R){ 46 if(ql<=L&&R<=qr){ 47 if(tp) x->addt(cv); 48 else x->sett(cv); 49 }else{ 50 int M=L+R>>1; 51 x->down(); 52 if(ql<=M) update(lson); 53 if(qr>M) update(rson); 54 x->update(); 55 } return; 56 } 57 void query(node*x,int L,int R){ 58 if(ql<=L&&R<=qr){ 59 _mi=min(_mi,x->mi); 60 _mx=max(_mx,x->mx); 61 _sm+=x->sm; 62 }else{ 63 int M=L+R>>1; 64 x->down(); 65 if(ql<=M) query(lson); 66 if(qr>M) query(rson); 67 } return; 68 } 69 struct ted{int x,y;ted*nxt;}adj[maxn<<1],*fch[maxn],*ms=adj; 70 void ade(int x,int y){ 71 *ms=(ted){x,y,fch[x]};fch[x]=ms++; 72 *ms=(ted){y,x,fch[y]};fch[y]=ms++; 73 return; 74 } 75 int dep[maxn],p[maxn],son[maxn],top[maxn],siz[maxn],fa[maxn],cz=0; 76 void dfs(int x){ 77 siz[x]=1;dep[x]=dep[fa[x]]+1; 78 for(ted*e=fch[x];e;e=e->nxt){ 79 int v=e->y;if(v!=fa[x]){ 80 fa[v]=x;dfs(v);siz[x]+=siz[v]; 81 if(siz[son[x]]<siz[v]) son[x]=v; 82 } 83 } return; 84 } 85 void build(int x,int tp){ 86 p[x]=++cz;top[x]=tp; 87 if(son[x]) build(son[x],tp); 88 for(ted*e=fch[x];e;e=e->nxt){ 89 int v=e->y; 90 if(v!=fa[x]&&v!=son[x]) build(v,v); 91 } return; 92 } 93 void update(int x,int y){ 94 int f1=top[x],f2=top[y]; 95 while(f1!=f2){ 96 if(dep[f1]<dep[f2]) swap(f1,f2),swap(x,y); 97 ql=p[f1];qr=p[x];update(root,1,n); 98 x=fa[f1];f1=top[x]; 99 } if(dep[x]>dep[y]) swap(x,y); 100 ql=p[x];qr=p[y];update(root,1,n);return; 101 } 102 void query(int x,int y){ 103 int f1=top[x],f2=top[y]; 104 while(f1!=f2){ 105 if(dep[f1]<dep[f2]) swap(f1,f2),swap(x,y); 106 ql=p[f1];qr=p[x];query(root,1,n); 107 x=fa[f1];f1=top[x]; 108 } if(dep[x]>dep[y]) swap(x,y); 109 ql=p[x];qr=p[y];query(root,1,n);return; 110 } 111 inline int read(){ 112 int x=0,sig=1;char ch=getchar(); 113 while(!isdigit(ch)){if(ch=='-')sig=-1;ch=getchar();} 114 while(isdigit(ch))x=10*x+ch-'0',ch=getchar(); 115 return x*=sig; 116 } 117 inline void write(int x){ 118 if(x==0){putchar('0');return;}if(x<0)putchar('-'),x=-x; 119 int len=0,buf[15];while(x)buf[len++]=x%10,x/=10; 120 for(int i=len-1;i>=0;i--)putchar(buf[i]+'0');return; 121 } 122 void init(){ 123 n=read(); 124 for(int i=1;i<n;i++) ade(read(),read()); 125 dfs(1);build(1,1); 126 for(int i=1;i<=n;i++) A[p[i]]=read(); 127 build(root,1,n); 128 return; 129 } 130 void work(){ 131 Q=read();int x,y; 132 while(Q--){ 133 tp=read();x=read();y=read(); 134 if(tp!=2) cv=read(),update(x,y); 135 else{ 136 _mi=inf;_mx=-inf;_sm=0;query(x,y); 137 write(_mx);PAU;write(_mi);PAU;write(_sm);ENT; 138 } 139 } 140 return; 141 } 142 void print(){ 143 return; 144 } 145 int main(){init();work();print();return 0;}
数组线段树:
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<queue> 6 #include<cstring> 7 #define PAU putchar(' ') 8 #define ENT putchar('\n') 9 using namespace std; 10 const int maxn=100000+10,maxn3=300000+10,inf=-1u>>1; 11 struct Tedge{int x,y,next;}adj[maxn*2];int ms=0,fch[maxn]; 12 int n,Q; 13 void AddEdge(int v,int u){ 14 adj[++ms]=(Tedge){u,v,fch[u]};fch[u]=ms; 15 adj[++ms]=(Tedge){v,u,fch[v]};fch[v]=ms; 16 return; 17 } 18 int maxv[maxn3],minv[maxn3],sumv[maxn3],setv[maxn3],addv[maxn3],A[maxn]; 19 void pushup(int o,int lc,int rc){ 20 minv[o]=min(minv[lc],minv[rc]); 21 maxv[o]=max(maxv[lc],maxv[rc]); 22 sumv[o]=sumv[lc]+sumv[rc]; 23 return; 24 } 25 void pushdown(int o,int lc,int rc){ 26 if(setv[o]>=0){ 27 setv[lc]=setv[rc]=setv[o]; 28 addv[lc]=addv[rc]=0; 29 setv[o]=-1; 30 } if(addv[o]){ 31 addv[lc]+=addv[o]; 32 addv[rc]+=addv[o]; 33 addv[o]=0; 34 } return; 35 } 36 void maintain(int o,int L,int R){ 37 int lc=o<<1,rc=lc|1; 38 if(L<R&&setv[o]<0) pushup(o,lc,rc); 39 if(setv[o]>=0){ 40 minv[o]=maxv[o]=setv[o]; 41 sumv[o]=(R-L+1)*setv[o]; 42 } if(addv[o]){ 43 minv[o]+=addv[o]; 44 maxv[o]+=addv[o]; 45 sumv[o]+=(R-L+1)*addv[o]; 46 } return; 47 } 48 int _min,_max,_sum,ql,qr,tp,cv; 49 void update(int o,int L,int R){ 50 if(ql<=L&&R<=qr){ 51 if(tp) addv[o]+=cv; 52 else setv[o]=cv,addv[o]=0; 53 } else{ 54 int M=L+R>>1,lc=o<<1,rc=lc|1; 55 pushdown(o,lc,rc); 56 if(ql<=M) update(lc,L,M); else maintain(lc,L,M); 57 if(qr>M) update(rc,M+1,R); else maintain(rc,M+1,R); 58 } maintain(o,L,R);return; 59 } 60 void build(int o,int L,int R){ 61 if(L==R) setv[o]=A[L]; 62 else{ 63 int M=L+R>>1,lc=o<<1,rc=lc|1; 64 build(lc,L,M);build(rc,M+1,R); 65 } maintain(o,L,R);return; 66 } 67 void query(int o,int L,int R,int add){ 68 if(setv[o]>=0){ 69 int change=setv[o]+addv[o]+add; 70 _sum+=(min(R,qr)-max(L,ql)+1)*change; 71 _min=min(_min,change); 72 _max=max(_max,change); 73 } else if(ql<=L&&R<=qr){ 74 _sum+=sumv[o]+(R-L+1)*add; 75 _min=min(_min,minv[o]+add); 76 _max=max(_max,maxv[o]+add); 77 } else{ 78 int M=L+R>>1,lc=o<<1,rc=lc|1; 79 if(ql<=M) query(lc,L,M,add+addv[o]); 80 if(M<qr) query(rc,M+1,R,add+addv[o]); 81 } return; 82 } 83 int dep[maxn],siz[maxn],top[maxn],p[maxn],fa[maxn],son[maxn]; 84 void dfs(int u){ 85 siz[u]=1;dep[u]=dep[fa[u]]+1; 86 for(int i=fch[u];i;i=adj[i].next){ 87 int v=adj[i].y; 88 if(v!=fa[u]){ 89 fa[v]=u;dfs(v); 90 if(siz[son[u]]<siz[v]) son[u]=v; 91 siz[u]+=siz[v]; 92 } 93 } return; 94 } 95 int cz=0; 96 void build(int u,int tp){ 97 p[u]=++cz;top[u]=tp; 98 if(son[u]) build(son[u],tp); 99 for(int i=fch[u];i;i=adj[i].next){ 100 int v=adj[i].y; 101 if(v!=fa[u]&&v!=son[u]) build(v,v); 102 } return; 103 } 104 void query(int a,int b){ 105 int f1=top[a],f2=top[b]; 106 while(f1!=f2){ 107 if(dep[f1]<dep[f2]) swap(a,b),swap(f1,f2); 108 ql=p[f1];qr=p[a];query(1,1,n,0); 109 a=fa[f1];f1=top[a]; 110 } 111 if(dep[a]>dep[b]) swap(a,b); 112 ql=p[a];qr=p[b];query(1,1,n,0);return; 113 } 114 void update(int a,int b){ 115 int f1=top[a],f2=top[b]; 116 while(f1!=f2){ 117 if(dep[f1]<dep[f2]) swap(a,b),swap(f1,f2); 118 ql=p[f1];qr=p[a];update(1,1,n); 119 a=fa[f1];f1=top[a]; 120 } 121 if(dep[a]>dep[b]) swap(a,b); 122 ql=p[a];qr=p[b];update(1,1,n);return; 123 } 124 inline int read(){ 125 int x=0,sig=1;char ch=getchar(); 126 while(!isdigit(ch)){if(ch=='-')sig=-1;ch=getchar();} 127 while(isdigit(ch))x=10*x+ch-'0',ch=getchar(); 128 return x*=sig; 129 } 130 inline void write(int x){ 131 if(x==0){putchar('0');return;}if(x<0)putchar('-'),x=-x; 132 int len=0,buf[15];while(x)buf[len++]=x%10,x/=10; 133 for(int i=len-1;i>=0;i--)putchar(buf[i]+'0');return; 134 } 135 void init(){ 136 memset(setv,-1,sizeof(setv)); 137 n=read(); 138 for(int i=1;i<n;i++) AddEdge(read(),read()); 139 dfs(1);build(1,1); 140 for(int i=1;i<=n;i++) A[p[i]]=read();//这么写跑的更快 141 build(1,1,n); 142 /*for(int i=1;i<=n;i++){//这样慢 143 ql=qr=p[i];cv=read(); 144 update(1,1,n); 145 }*/ 146 Q=read(); 147 return; 148 } 149 void work(){ 150 int a,b; 151 while(Q--){ 152 tp=read();a=read();b=read(); 153 if(tp==2){//query 154 _sum=0;_min=inf;_max=-inf; 155 query(a,b); 156 write(_max);PAU;write(_min);PAU;write(_sum);ENT; 157 } else cv=read(),update(a,b); 158 } 159 return; 160 } 161 void print(){ 162 return; 163 } 164 int main(){init();work();print();return 0;}
大数据跑LCT还是快:
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<queue> 6 #include<cstring> 7 #define PAU putchar(' ') 8 #define ENT putchar('\n') 9 using namespace std; 10 const int maxn=100000+10,inf=-1u>>1; 11 inline int read(){ 12 int x=0,sig=1;char ch=getchar(); 13 while(!isdigit(ch)){if(ch=='-')sig=-1;ch=getchar();} 14 while(isdigit(ch))x=10*x+ch-'0',ch=getchar(); 15 return x*=sig; 16 } 17 inline void write(int x){ 18 if(x==0){putchar('0');return;}if(x<0)putchar('-'),x=-x; 19 int len=0,buf[15];while(x)buf[len++]=x%10,x/=10; 20 for(int i=len-1;i>=0;i--)putchar(buf[i]+'0');return; 21 } 22 struct node { 23 node *ch[2],*fa; 24 bool rev; 25 int x,sm,siz,add,mi,mx,set; 26 inline void add_rev_tag(){ 27 swap(ch[0],ch[1]);rev^=1;return; 28 } 29 inline void add_plus_tag(int a){ 30 sm+=siz*a;x+=a;add+=a; 31 if(mi!=inf) mi+=a; 32 if(mx!=-inf) mx+=a; 33 return; 34 } 35 inline void add_set_tag(int a){ 36 x=set=a;add=0;sm=a*siz; 37 if(mi!=inf) mi=set; 38 if(mx!=-inf) mx=set; 39 } 40 inline void down(){ 41 if(rev){ 42 if(ch[0]) ch[0]->add_rev_tag(); 43 if(ch[1]) ch[1]->add_rev_tag(); 44 rev=0; 45 } 46 if(set){ 47 if(ch[0]) ch[0]->add_set_tag(set); 48 if(ch[1]) ch[1]->add_set_tag(set); 49 set=0; 50 } 51 if(add){ 52 if(ch[0]) ch[0]->add_plus_tag(add); 53 if(ch[1]) ch[1]->add_plus_tag(add); 54 add=0; 55 } 56 return; 57 } 58 inline void update(){ 59 sm=0;siz=1;mi=inf;mx=-inf; 60 if(ch[0]) sm+=ch[0]->sm,siz+=ch[0]->siz,mi=min(mi,ch[0]->mi),mx=max(mx,ch[0]->mx); 61 if(ch[1]) sm+=ch[1]->sm,siz+=ch[1]->siz,mi=min(mi,ch[1]->mi),mx=max(mx,ch[1]->mx); 62 if(!x) return; 63 mi=min(x,mi); 64 mx=max(x,mx); 65 sm+=x; 66 return; 67 } 68 }lct[maxn]; 69 inline int get_parent(node *x,node *&fa){return (fa=x->fa)?fa->ch[0]==x?0:fa->ch[1]==x?1:-1:-1;} 70 inline void rotate(node *x){ 71 int t1,t2; 72 node *fa,*gfa; 73 t1=get_parent(x,fa); 74 t2=get_parent(fa,gfa); 75 if ((fa->ch[t1]=x->ch[t1^1])) fa->ch[t1]->fa=fa; 76 x->ch[t1^1]=fa;fa->fa=x;x->fa=gfa; 77 if (t2!=-1) gfa->ch[t2]=x; 78 fa->update();return; 79 } 80 inline void pushdown(node *x){ 81 static node *stack[maxn]; 82 int cnt=0; 83 while(1){ 84 stack[cnt++]=x; 85 node *fa=x->fa; 86 if (!fa || (fa->ch[0]!=x && fa->ch[1]!=x)) break; 87 x=fa; 88 } 89 while(cnt--) stack[cnt]->down(); 90 return; 91 } 92 inline node * splay(node *x){ 93 pushdown(x); 94 while(1){ 95 int t1,t2; 96 node *fa,*gfa; 97 t1=get_parent(x,fa); 98 if(t1==-1) break; 99 t2=get_parent(fa,gfa); 100 if(t2==-1){ 101 rotate(x);break; 102 } else if (t1==t2){ 103 rotate(fa);rotate(x); 104 } else{ 105 rotate(x);rotate(x); 106 } 107 } 108 x->update(); 109 return x; 110 } 111 inline node * access(node *x){ 112 node *ret=NULL; 113 while (x) splay(x)->ch[1]=ret,(ret=x)->update(),x=x->fa; 114 return ret; 115 } 116 inline void makeroot(int x){access(lct+x)->add_rev_tag();} 117 inline void link(int u,int v){ 118 makeroot(u);splay(lct+u)->fa=lct+v;return; 119 } 120 inline void cut(int u,int v){ 121 makeroot(u); 122 node *p=(access(lct+v),splay(lct+v)); 123 p->ch[0]->fa=NULL; 124 p->ch[0]=NULL; 125 p->update(); 126 } 127 int n,q; 128 int main(){ 129 n=read(); 130 int i; 131 for(i=1;i<=n;i++){ 132 lct[i].x=lct[i].sm=0; 133 lct[i].siz=1; 134 lct[i].add=0; 135 lct[i].mi=inf; 136 lct[i].mx=-inf; 137 lct[i].set=0; 138 } 139 for(i=1;i<n;i++){ 140 int u,v; 141 u=read();v=read(); 142 link(u,v); 143 } 144 for(int i=1;i<=n;i++){ 145 lct[i].x=read();lct[i].update(); 146 } 147 q=read(); 148 int x,y,c; 149 while(q--){ 150 c=read();x=read();y=read(); 151 if(c==0) makeroot(x),access(y+lct)->add_set_tag(read()); 152 else if(c==1) makeroot(x),access(y+lct)->add_plus_tag(read()); 153 else{ 154 makeroot(x);node*t=access(y+lct);splay(t); 155 write(t->mx);PAU;write(t->mi);PAU;write(t->sm);ENT; 156 } 157 } 158 return 0; 159 }