hdu5002 Tree

动态树的基本操作:

1. 添边、删边。

2. 修改一棵树一条链的权值。

3. 给一棵树一条链的权值加上一个数。

4. 查询一棵树一条链上的点,第二大权值、权值第二大点的个数。

  1 #include<bits/stdc++.h>
  2 #define lc c[x][0]
  3 #define rc c[x][1]
  4 using namespace std;
  5 const int N=1e5+10;
  6 const int inf=2e9;
  7 int f[N],c[N][2],val[N];
  8 int st[N];
  9 int mx1[N],mx2[N],c1[N],c2[N],siz[N];
 10 int tag_a[N],tag_c[N];
 11 bool rev[N];
 12 
 13 void init(int n){
 14     for(int i=1;i<=n;i++){
 15         f[i]=c[i][0]=c[i][1]=0;
 16         mx1[i]=val[i],mx2[i]=-inf;
 17         c1[i]=1,c2[i]=0;
 18         siz[i]=1;
 19         rev[i]=tag_a[i]=tag_c[i]=0;
 20     }
 21 }
 22 
 23 inline bool nroot(int x){//判断节点是否为一个Splay的根
 24     return c[f[x]][0]==x||c[f[x]][1]==x;
 25 }
 26 
 27 void solve(int x,int v,int cnt){
 28     if(v>mx1[x]) mx2[x]=mx1[x],mx1[x]=v,c2[x]=c1[x],c1[x]=cnt;
 29     else if(v==mx1[x]) c1[x]+=cnt;
 30     else if(v>mx2[x]) mx2[x]=v,c2[x]=cnt;
 31     else if(v==mx2[x]) c2[x]+=cnt;
 32 }
 33 
 34 void add(int x,int v){
 35     val[x]+=v; mx1[x]+=v;
 36     if(mx2[x]!=-inf) mx2[x]+=v;
 37     tag_a[x]+=v;
 38 }
 39 
 40 void change(int x,int v){
 41     val[x]=mx1[x]=v;
 42     mx2[x]=-inf;
 43     c1[x]=siz[x],c2[x]=0;
 44     tag_c[x]=v;
 45     if(tag_a[x]) tag_a[x]=0;
 46 }
 47 
 48 void pushup(int x){//上传信息
 49     mx1[x]=val[x],mx2[x]=-inf;
 50     c1[x]=c2[x]=0;
 51     solve(x,val[x],1);
 52     if(lc) solve(x,mx1[lc],c1[lc]),solve(x,mx2[lc],c2[lc]);
 53     if(rc) solve(x,mx1[rc],c1[rc]),solve(x,mx2[rc],c2[rc]);
 54     siz[x]=siz[lc]+siz[rc]+1;
 55 }
 56 
 57 inline void pushr(int x){//翻转操作
 58     int t=lc;
 59     lc=rc,rc=t;
 60     rev[x]^=1;
 61 }
 62 
 63 void pushdown(int x){//判断并释放懒标记
 64     if(rev[x]){
 65         if(lc) pushr(lc);
 66         if(rc) pushr(rc);
 67         rev[x]=0;
 68     }
 69     if(tag_c[x]!=-inf){
 70         if(lc) change(lc,tag_c[x]);
 71         if(rc) change(rc,tag_c[x]);
 72         tag_c[x]=-inf;
 73     }
 74     if(tag_a[x]){
 75         if(lc) add(lc,tag_a[x]);
 76         if(rc) add(rc,tag_a[x]);
 77         tag_a[x]=0;
 78     }
 79 }
 80 
 81 void rotate(int x){//一次旋转
 82     int y=f[x],z=f[y],k=c[y][1]==x,w=c[x][!k];
 83     if(nroot(y))c[z][c[z][1]==y]=x;c[x][!k]=y;c[y][k]=w;
 84     if(w)f[w]=y;f[y]=x;f[x]=z;
 85     pushup(y);
 86 }
 87 
 88 void splay(int x){
 89     int y=x,z=0;
 90     st[++z]=y;
 91     while(nroot(y)) st[++z]=y=f[y];
 92     while(z) pushdown(st[z--]);
 93     while(nroot(x)){
 94         y=f[x];z=f[y];
 95         if(nroot(y))
 96             rotate((c[y][0]==x)^(c[z][0]==y)?x:y);
 97         rotate(x);
 98     }
 99     pushup(x);
100 }
101 
102 void access(int x){//访问
103     for(int y=0;x;x=f[y=x])
104         splay(x),rc=y,pushup(x);
105 }
106 
107 void makeroot(int x){//换根
108     access(x);splay(x);
109     pushr(x);
110 }
111 
112 int findroot(int x){//找根(在真实的树中的)
113     access(x);splay(x);
114     while(lc)pushdown(x),x=lc;
115     splay(x);
116     return x;
117 }
118 
119 void split(int x,int y){//提取路径
120     makeroot(x);
121     access(y);splay(y);
122 }
123 
124 void link(int x,int y){//连边
125     makeroot(x);
126     if(findroot(y)!=x)f[x]=y;
127 }
128 
129 void cut(int x,int y){//断边
130     makeroot(x);
131     if(findroot(y)==x&&f[y]==x&&!c[y][0]){
132         f[y]=c[x][1]=0;
133         pushup(x);
134     }
135 }
136 
137 void query(int x,int y){
138     split(x,y);
139     if(c1[y]==siz[y]) printf("ALL SAME
");
140     else printf("%d %d
",mx2[y],c2[y]);
141 }
142 
143 int main()
144 {
145     int T;
146     scanf("%d",&T);
147     for(int cas=1;cas<=T;cas++){
148         int n,m;
149         scanf("%d%d",&n,&m);
150         for(int i=1;i<=n;i++){
151             scanf("%d",&val[i]);
152         }
153         init(n);
154         for(int i=1;i<n;i++){
155             int u,v;
156             scanf("%d%d",&u,&v);
157             link(u,v);
158         }
159         printf("Case #%d:
",cas);
160         while(m--){
161             int tp;
162             scanf("%d",&tp);
163             if(tp==1){
164                 int x,y,a,b;
165                 scanf("%d%d%d%d",&x,&y,&a,&b);
166                 cut(x,y);
167                 link(a,b);
168             }
169             else if(tp==2){
170                 int a,b,x;
171                 scanf("%d%d%d",&a,&b,&x);
172                 split(a,b);
173                 change(b,x);
174             }
175             else if(tp==3){
176                 int a,b,d;
177                 scanf("%d%d%d",&a,&b,&d);
178                 split(a,b);
179                 add(b,d);
180             }
181             else{
182                 int a,b;
183                 scanf("%d%d",&a,&b);
184                 query(a,b);
185             }
186         }
187     }
188     return 0;
189 }
原文地址:https://www.cnblogs.com/--HY--/p/13510437.html