数据结构(LCT动态树):BZOJ 1036: [ZJOI2008]树的统计Count

1036: [ZJOI2008]树的统计Count

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 12266  Solved: 4945
[Submit][Status][Discuss]

Description

  一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成
一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I
II. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身

Input

  输入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有
一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数q,表示操作
的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。
对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。

Output

  对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。

Sample Input

4
1 2
2 3
4 1
4 2 1 3
12
QMAX 3 4
QMAX 3 3
QMAX 3 2
QMAX 2 3
QSUM 3 4
QSUM 2 1
CHANGE 1 5
QMAX 3 4
CHANGE 3 6
QMAX 3 4
QMAX 2 4
QSUM 3 4

Sample Output

4
1
2
2
10
6
5
6
5
16
  模板题,权当复习……
  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 using namespace std;
  5 const int maxn=30010;
  6 const int INF=1000000000;
  7 
  8 int n,Q;
  9 bool rt[maxn];
 10 long long sum[maxn];
 11 int ch[maxn][2],fa[maxn];
 12 int Mx[maxn],key[maxn],flip[maxn];
 13 int cnt,fir[maxn],nxt[maxn<<1],to[maxn<<1];
 14 
 15 void addedge(int a,int b){
 16     nxt[++cnt]=fir[a];fir[a]=cnt;to[cnt]=b;
 17 }
 18 
 19 void Push_up(int x){
 20     sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+key[x];
 21     Mx[x]=max(max(Mx[ch[x][0]],Mx[ch[x][1]]),key[x]);
 22 }
 23 
 24 void Flip(int x){
 25     swap(ch[x][0],ch[x][1]);
 26     flip[x]^=1;
 27 }
 28 
 29 void Push_down(int x){
 30     if(flip[x]){
 31         Flip(ch[x][0]);
 32         Flip(ch[x][1]);
 33         flip[x]=0;
 34     }    
 35 }
 36 
 37 void Rotate(int x){
 38     int y=fa[x],g=fa[y],c=ch[y][1]==x;
 39     ch[y][c]=ch[x][c^1];fa[ch[y][c]]=y;
 40     ch[x][c^1]=y;fa[y]=x;fa[x]=g;
 41     if(rt[y])rt[y]=false,rt[x]=true;
 42     else ch[g][ch[g][1]==y]=x;
 43     Push_up(y);
 44 }
 45 
 46 void P(int x){
 47     if(!rt[x])P(fa[x]);
 48     Push_down(x);
 49 }
 50 
 51 void Splay(int x){
 52     P(x);
 53     for(int y=fa[x];!rt[x];Rotate(x),y=fa[x])
 54         if(!rt[y])Rotate((ch[fa[y]][1]==y)==(ch[y][1]==x)?y:x);
 55     Push_up(x);
 56 }
 57 
 58 void Access(int x){
 59     int y=0;
 60     while(x){
 61         Splay(x);
 62         rt[ch[x][1]]=true;
 63         rt[ch[x][1]=y]=false;
 64         Push_up(x);
 65         x=fa[y=x];
 66     }
 67 }
 68 
 69 void Lca(int &x,int &y){
 70     Access(y);y=0;
 71     while(true){
 72         Splay(x);
 73         if(!fa[x])return;
 74         rt[ch[x][1]]=true;
 75         rt[ch[x][1]=y]=false;
 76         Push_up(x);
 77         x=fa[y=x];
 78     }
 79 }    
 80 
 81 void Change(int x,int y){
 82     Splay(x);
 83     key[x]=y;
 84     Push_up(x);
 85 }
 86 
 87 void DFS(int x){
 88     for(int i=fir[x];i;i=nxt[i])
 89         if(fa[x]!=to[i]){
 90             fa[to[i]]=x;
 91             DFS(to[i]);
 92         }
 93 }
 94 
 95 char op[5];
 96 int main(){
 97     Mx[0]=-INF;
 98     scanf("%d",&n);
 99     for(int i=1,a,b;i<n;i++){
100         scanf("%d%d",&a,&b);
101         addedge(a,b);
102         addedge(b,a);
103     }
104     for(int i=1;i<=n;i++){
105         scanf("%d",&key[i]);
106         rt[i]=true;
107     }
108     DFS(1);
109     scanf("%d",&Q);
110     int x,y;
111     while(Q--){
112         scanf("%s",op);
113         if(op[0]=='C'){
114             scanf("%d%d",&x,&y);
115             Change(x,y);
116         }
117         else{
118             scanf("%d%d",&x,&y);Lca(x,y);
119             if(op[1]=='M')
120                 printf("%d\n",max(max(key[x],Mx[ch[x][1]]),Mx[y]));
121             else
122                 printf("%lld\n",(long long)(key[x]+sum[ch[x][1]]+sum[y]));    
123         }
124     }
125     return 0;
126 }

 

posted @ 2016-06-13 15:59  TenderRun  阅读(191)  评论(0编辑  收藏  举报