[ZJOI2008]树的统计
题目描述
一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。
我们将以下面的形式来要求你对这棵树完成一些操作:
I. CHANGE u t : 把结点u的权值改为t
II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值
III. QSUM u v: 询问从点u到点v的路径上的节点的权值和
注意:从点u到点v的路径上的节点包括u和v本身
输入格式
输入文件的第一行为一个整数n,表示节点的个数。
接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。
接下来一行n个整数,第i个整数wi表示节点i的权值。
接下来1行,为一个整数q,表示操作的总数。
接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。
输出格式
对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。
输入输出样例
输入 #1
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
4 1 2 2 10 6 5 6 5 16
说明/提示
对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。
分析:
一道比树剖模板题还简单的。。。模板题???emmmm。。。
CODE:
1 #include<cmath> 2 #include<cstdio> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 const int N=30005; 8 const int M=100005; 9 int n,m,summ,maxx; 10 int seg[M],rev[M],size[M],son[M],top[M],dep[M]; 11 int sum[M],num[M],father[M],Max[M]; 12 int head[M],next[M],to[M],tot; 13 inline int read(){ 14 int res=0; 15 int f=1; 16 char c=getchar(); 17 while (c>'9'||c<'0') { 18 if (c=='-') f=-1; 19 c=getchar(); 20 } 21 while (c<='9'&&c>='0') { 22 res=(res<<3)+(res<<1)+c-'0'; 23 c=getchar(); 24 } 25 return res*f; 26 } 27 void add(int u,int v){ 28 next[++tot]=head[u]; 29 head[u]=tot; 30 to[tot]=v; 31 return ; 32 } 33 inline void insert(int u,int v){ 34 add(u,v); 35 add(v,u); 36 return ; 37 } 38 void query(int k,int l,int r,int L,int R){ 39 if (L>r||R<l) return ; 40 if (L<=l&&r<=R) { 41 summ+=sum[k]; 42 maxx=max(maxx,Max[k]); 43 return ; 44 } 45 int m=l+r>>1; 46 if (m>=L) query(k<<1,l,m,L,R); 47 if (m<R) query(k<<1|1,m+1,r,L,R); 48 } 49 void change(int k,int l,int r,int val,int pos){ 50 if (pos>r||pos<l) return ; 51 if (l==r&&r==pos){ 52 sum[k]=val; 53 Max[k]=val; 54 return ; 55 } 56 int m=l+r>>1; 57 if (m>=pos) change(k<<1,l,m,val,pos); 58 if (m<pos) change(k<<1|1,m+1,r,val,pos); 59 sum[k]=sum[k<<1]+sum[k<<1|1]; 60 Max[k]=max(Max[k<<1],Max[k<<1|1]); 61 } 62 void build(int k,int l,int r){ 63 int m=l+r>>1; 64 if (l==r){Max[k]=sum[k]=num[rev[l]];return;} 65 build(k<<1,l,m); 66 build(k<<1|1,m+1,r); 67 sum[k]=sum[k<<1]+sum[k<<1|1]; 68 Max[k]=max(Max[k<<1],Max[k<<1|1]); 69 return; 70 } 71 void dfs1(int u,int fa){ 72 dep[u]=dep[fa]+1; 73 father[u]=fa; 74 size[u]=1; 75 for (int i=head[u];i;i=next[i]){ 76 int v=to[i]; 77 if (v!=fa){ 78 dfs1(v,u); 79 size[u]+=size[v]; 80 if (size[v]>size[son[u]]) son[u]=v; 81 } 82 } 83 return; 84 } 85 void dfs2(int u,int fa){ 86 if (son[u]){ 87 seg[son[u]]=++seg[0]; 88 top[son[u]]=top[u]; 89 rev[seg[0]]=son[u]; 90 dfs2(son[u],u); 91 } 92 for (int i=head[u];i;i=next[i]){ 93 int v=to[i]; 94 if (!top[v]) { 95 seg[v]=++seg[0]; 96 rev[seg[0]]=v; 97 top[v]=v; 98 dfs2(v,u); 99 } 100 } 101 return; 102 } 103 void ask(int x,int y){ 104 int fx=top[x],fy=top[y]; 105 while (fx!=fy){ 106 if (dep[fx]<dep[fy]) swap(x,y),swap(fx,fy); 107 query(1,1,seg[0],seg[fx],seg[x]); 108 x=father[fx];fx=top[x]; 109 } 110 if (dep[x]>dep[y]) swap(x,y); 111 query(1,1,seg[0],seg[x],seg[y]); 112 } 113 int main() { 114 n=read(); 115 for (int i=1;i<n;i++) insert(read(),read()); 116 for (int i=1;i<=n;i++) num[i]=read(); 117 dfs1(1,0); 118 seg[0]=seg[1]=top[1]=rev[1]=1; 119 dfs2(1,0); 120 build(1,1,seg[0]); 121 m=read(); 122 while (m--){ 123 char s[15]; 124 int u,v; 125 cin>>s+1; 126 u=read(),v=read(); 127 if (s[1]=='C') change(1,1,seg[0],v,seg[u]); 128 else{ 129 summ=0; 130 maxx=-1<<30; 131 ask(u,v); 132 if (s[2]=='M') cout<<maxx<<endl; 133 else cout<<summ<<endl; 134 } 135 } 136 //system("pause"); 137 return 0; 138 }