数据结构(LCT动态树):BZOJ 1036: [ZJOI2008]树的统计Count
1036: [ZJOI2008]树的统计Count
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 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
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
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 }
尽最大的努力,做最好的自己!