COJ 1008 WZJ的数据结构(八) 树上操作

传送门: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('
')
  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('
')
  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('
')
  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 }
原文地址:https://www.cnblogs.com/chxer/p/4474009.html