hdu 5002 Tree(LCT裸题)

题目链接:hdu 5002 Tree

题意:

给你一棵树,每个节点有个权值。

现在有四种操作

1. 删一条边加一条边,保证操作后还是一棵树。

2. 将一条链的节点的权值设为x.

3. 将一条链的节点的权值加上x.

4. 询问一条链的第二大权值,并且输出有多少个。

题解:

很裸的LCT,维护一下就行了。

  1 #include
  2 #define F(i,a,b) for(int i=a;i<=b;i++)
  3 #define mst(a,b) memset(a,b,sizeof(a))
  4 using namespace std;
  5 typedef pair<int,int>P;
  6 
  7 namespace LCT
  8 {
  9     const int N=1e5+7,inf=2e9+7;
 10     int f[N],son[N][2],val[N],tmp[N],sum[N],lazy[N],laop[N];
 11     int g[N],v[N*2],nxt[N*2],ed;bool rev[N];
 12     P mx[N][2],tp[10];
 13     void clear(int n)
 14     {
 15         F(i,1,n)f[i]=son[i][0]=son[i][1]=0;
 16         F(i,1,n)rev[i]=lazy[i]=laop[i]=g[i]=0;ed=0;
 17         F(i,1,n)mx[i][0]=mx[i][1]=P(-inf,0);
 18     }
 19     void adg(int x,int y){v[++ed]=y,nxt[ed]=g[x],g[x]=ed;}
 20     void build(int x=1){
 21         sum[x]=1,mx[x][0]=P(val[x],1);
 22         for(int i=g[x];i;i=nxt[i])
 23             if(!f[v[i]]&&v[i]!=1)f[v[i]]=x,build(v[i]);
 24     }
 25     bool isroot(int x){return !f[x]||son[f[x]][0]!=x&&son[f[x]][1]!=x;}
 26     void rev1(int x){if(!x)return;swap(son[x][0],son[x][1]);rev[x]^=1;}
 27     void add(int x,int c,int op)
 28     {
 29         if(!x)return;
 30         if(op==2)
 31         {
 32             val[x]+=c,lazy[x]+=c;
 33             mx[x][0].first+=c;
 34             if(mx[x][1].first!=-inf)mx[x][1].first+=c;
 35         }
 36         else if(op==1)
 37         {
 38             val[x]=c,lazy[x]=c;
 39             mx[x][0]=P(c,sum[x]);
 40             mx[x][1]=P(-inf,0);
 41             laop[x]=1;
 42         }
 43         if(!laop[x])laop[x]=op;
 44     }
 45     void pb(int x){
 46         if(rev[x])rev1(son[x][0]),rev1(son[x][1]),rev[x]=0;
 47         if(laop[x])add(son[x][0],lazy[x],laop[x]),add(son[x][1],lazy[x],laop[x]),lazy[x]=laop[x]=0;
 48     }
 49     void up(int x){
 50         sum[x]=1;
 51         int ct=0;
 52         tp[ct=1]=P(val[x],1);
 53         if(son[x][0])
 54         {
 55            sum[x]+=sum[son[x][0]];
 56            F(i,0,1)tp[++ct]=mx[son[x][0]][i];
 57         }
 58         if(son[x][1])
 59         {
 60             sum[x]+=sum[son[x][1]];
 61             F(i,0,1)tp[++ct]=(mx[son[x][1]][i]);
 62         }
 63         sort(tp+1,tp+1+ct,greater

()); 64 int cnt=1; 65 F(i,2,ct) 66 { 67 if(tp[i].first==tp[cnt].first)tp[cnt].second+=tp[i].second; 68 else tp[++cnt]=tp[i]; 69 } 70 mx[x][0]=tp[1]; 71 if(cnt>1)mx[x][1]=tp[2]; 72 else mx[x][1]=P(-inf,0); 73 } 74 void rotate(int x){ 75 int y=f[x],w=son[y][1]==x; 76 son[y][w]=son[x][w^1]; 77 if(son[x][w^1])f[son[x][w^1]]=y; 78 if(f[y]){ 79 int z=f[y]; 80 if(son[z][0]==y)son[z][0]=x;else if(son[z][1]==y)son[z][1]=x; 81 } 82 f[x]=f[y];f[y]=x;son[x][w^1]=y;up(y); 83 } 84 void splay(int x){ 85 int s=1,i=x,y;tmp[1]=i; 86 while(!isroot(i))tmp[++s]=i=f[i]; 87 while(s)pb(tmp[s--]); 88 while(!isroot(x)){ 89 y=f[x]; 90 if(!isroot(y)){if((son[f[y]][0]==y)^(son[y][0]==x))rotate(x);else rotate(y);} 91 rotate(x); 92 } 93 up(x); 94 } 95 void access(int x){for(int y=0;x;y=x,x=f[x])splay(x),son[x][1]=y,up(x);} 96 int root(int x){access(x);splay(x);while(son[x][0])x=son[x][0];return x;} 97 void makeroot(int x){access(x);splay(x);rev1(x);} 98 void link(int x,int y){makeroot(x);f[x]=y;access(x);} 99 void cutf(int x){access(x);splay(x);f[son[x][0]]=0;son[x][0]=0;up(x);} 100 void cut(int x,int y){makeroot(x);cutf(y);} 101 void update(int x,int y,int c,int op){makeroot(x),access(y),splay(y),add(y,c,op);} 102 P ask(int x,int y){makeroot(x);access(y);splay(y);return mx[y][1];} 103 } 104 using namespace LCT; 105 int t,n,m,c,a,b,x,y,cas; 106 107 int main() 108 { 109 scanf("%d",&t); 110 while(t--) 111 { 112 scanf("%d%d",&n,&m); 113 clear(n); 114 F(i,1,n)scanf("%d",val+i); 115 F(i,2,n) 116 { 117 scanf("%d%d",&x,&y); 118 adg(x,y),adg(y,x); 119 } 120 build(),printf("Case #%d:\n",++cas); 121 F(i,1,m) 122 { 123 scanf("%d",&c); 124 if(c==1) 125 { 126 scanf("%d%d%d%d",&x,&y,&a,&b); 127 cut(x,y),link(a,b); 128 } 129 else if(c==2) 130 { 131 scanf("%d%d%d",&a,&b,&x); 132 update(a,b,x,1); 133 } 134 else if(c==3) 135 { 136 scanf("%d%d%d",&a,&b,&x); 137 update(a,b,x,2); 138 } 139 else 140 { 141 scanf("%d%d",&a,&b); 142 P ans=ask(a,b); 143 if(ans.first==-inf)puts("ALL SAME"); 144 else printf("%d %d\n",ans.first,ans.second); 145 } 146 147 } 148 } 149 return 0; 150 }

View Code

 

转载于:https://www.cnblogs.com/bin-gege/p/7738300.html

你可能感兴趣的:(hdu 5002 Tree(LCT裸题))