Codevs 2460 == BZOJ 1036 树的统计
2460 树的统计
2008年省队选拔赛浙江
时间限制: 2 s 空间限制: 128000 KB 题目等级 : 大师 Master
题目描述 Description
一棵树上有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本身
输入描述 Input Description
输入文件的第一行为一个整数n,表示节点的个数。
接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。
接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。
接下来1行,为一个整数q,表示操作的总数。
接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。
输出描述 Output Description
对于每个“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
数据范围及提示 Data Size & Hint
对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define maxn 300001 5 using namespace std; 6 int head[maxn],dep[maxn],fa[maxn],a[maxn]; 7 int pos[maxn],top[maxn],size[maxn],son[maxn]; 8 int tot,n,m,cnt,maxsize,x,y,num; 9 struct Edge{int next,to;}e[maxn<<1]; 10 struct Node{int l,r,max,sum;}tre[maxn<<2]; 11 int read(){ 12 int x=0,f=1;char c=getchar(); 13 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 14 while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} 15 return x*f; 16 } 17 int max(int a,int b){if(a>b)return a;else return b;} 18 void Add_Edge(int u,int v){ 19 e[++num].to=v;e[num].next=head[u];head[u]=num; 20 } 21 void DFS_First(int now,int pre,int deepth){ 22 dep[now] = deepth; fa[now] = pre; size[now] = 1; 23 for(int i=head[now];i;i=e[i].next){ 24 int v=e[i].to; 25 if(v!=pre){ 26 DFS_First(v,now,deepth+1); 27 size[now] += size[v]; 28 if(son[now]==-1||size[v]>size[son[now]]) 29 son[now]=v; 30 } 31 } 32 } 33 void Get_Pos(int u,int Top){ 34 int k=0;maxsize++; 35 pos[u]=maxsize;top[u]=Top; 36 if(!son[u])return; 37 Get_Pos(son[u],Top); 38 for(int i=head[u];i;i=e[i].next) 39 if(dep[e[i].to]>dep[u]&&e[i].to!=son[u]) 40 Get_Pos(e[i].to,e[i].to); 41 return; 42 } 43 void Build(int now,int l,int r){ 44 tre[now].l=l;tre[now].r=r; 45 if(l==r){ 46 tre[now].sum=tre[now].max=0;return ; 47 } 48 int mid=(l+r)>>1; 49 Build(now<<1,l,mid);Build(now<<1|1,mid+1,r); 50 tre[now].sum=tre[now<<1].sum+tre[now<<1|1].sum; 51 tre[now].max=max(tre[now<<1].max,tre[now<<1|1].max); 52 53 } 54 void Insert(int now,int poss,int val){ 55 if(tre[now].l==tre[now].r){ 56 tre[now].sum=tre[now].max=val;return; 57 } 58 int mid=(tre[now].l+tre[now].r)/2; 59 if(poss<=mid)Insert(now<<1,poss,val); 60 else if(poss>mid)Insert(now<<1|1,poss,val); 61 tre[now].sum=tre[now<<1].sum+tre[now<<1|1].sum; 62 tre[now].max=max(tre[now<<1].max,tre[now<<1|1].max); 63 } 64 int QueryMax(int now,int l,int r){ 65 if(l<=tre[now].l&&tre[now].r<=r)return tre[now].max; 66 int mid=(tre[now].l+tre[now].r)>>1,total=-1e9; 67 if(l<=mid)total=max(total,QueryMax(now<<1,l,r)); 68 if(r>mid)total=max(total,QueryMax(now<<1|1,l,r)); 69 return total; 70 } 71 int QuerySum(int now,int l,int r){ 72 if(l<=tre[now].l&&tre[now].r<=r)return tre[now].sum; 73 int mid=(tre[now].l+tre[now].r)>>1,total=0; 74 if(l<=mid)total+=QuerySum(now<<1,l,r); 75 if(r>mid)total+=QuerySum(now<<1|1,l,r); 76 return total; 77 } 78 int SolveMax(int u,int v){ 79 int ans=-1e9; 80 while(top[u]!=top[v]){ 81 if(dep[top[u]]<dep[top[v]])swap(u,v); 82 ans=max(ans,QueryMax(1,pos[top[u]],pos[u])); 83 u=fa[top[u]]; 84 } 85 if(pos[u]>pos[v]) swap(u,v); 86 ans=max(ans,QueryMax(1,pos[u],pos[v])); 87 return ans; 88 } 89 int SolveSum(int u,int v){ 90 int ans=0; 91 while(top[u]!=top[v]){ 92 if(dep[top[u]]<dep[top[v]])swap(u,v); 93 ans+=QuerySum(1,pos[top[u]],pos[u]); 94 u=fa[top[u]]; 95 } 96 if(pos[u]>pos[v])swap(u,v); 97 ans+=QuerySum(1,pos[u],pos[v]); 98 return ans; 99 } 100 int main(){ 101 n=read(); 102 for(int i=1;i<n;i++){ 103 x=read();y=read(); 104 Add_Edge(x,y);Add_Edge(y,x); 105 } 106 for(int i=1;i<=n;i++) a[i]=read(); 107 DFS_First(1,0,0); 108 Get_Pos(1,1); 109 Build(1,1,maxsize); 110 for(int i=1;i<=n;i++) 111 Insert(1,pos[i],a[i]); 112 m=read();char sp[25]; 113 while(m--){ 114 scanf("%s",sp);scanf("%d%d",&x,&y); 115 if(sp[0]=='C')a[x]=y,Insert(1,pos[x],y); 116 else{ 117 if(sp[1]=='M') printf("%d\n",SolveMax(x,y)); 118 else printf("%d\n",SolveSum(x,y)); 119 } 120 } 121 return 0; 122 }