[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之间。
模板水题
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int N=30005; 7 struct Node 8 { 9 int next,to; 10 }edge[2*N]; 11 int cm[4*N],cs[4*N]; 12 int size[N],top[N],num,head[N],son[N],dfn[N],id[N],cnt,fa[N]; 13 int dep[N],w[N],n,q; 14 char s[21]; 15 void add(int u,int v) 16 { 17 num++; 18 edge[num].next=head[u]; 19 head[u]=num; 20 edge[num].to=v; 21 } 22 void dfs1(int x,int pa) 23 {int i; 24 size[x]=1; 25 for (i=head[x];i;i=edge[i].next) 26 { 27 int v=edge[i].to; 28 if (v==pa) continue; 29 dfs1(v,x); 30 size[x]+=size[v]; 31 if (size[v]>size[son[x]]) son[x]=v; 32 } 33 } 34 void dfs2(int x,int pa,int tp) 35 {int i; 36 dfn[x]=++cnt; 37 id[cnt]=x;fa[x]=pa; 38 top[x]=tp;dep[x]=dep[pa]+1; 39 if (son[x]) 40 dfs2(son[x],x,tp); 41 for (i=head[x];i;i=edge[i].next) 42 { 43 int v=edge[i].to; 44 if (v==pa||v==son[x]) continue; 45 dfs2(v,x,v); 46 } 47 } 48 void pushup(int rt) 49 { 50 cm[rt]=max(cm[rt<<1],cm[rt<<1|1]); 51 cs[rt]=cs[rt<<1]+cs[rt<<1|1]; 52 } 53 void build(int rt,int l,int r) 54 { 55 if (l==r) 56 { 57 cm[rt]=w[id[l]]; 58 cs[rt]=w[id[l]]; 59 return; 60 } 61 int mid=(l+r)>>1; 62 build(rt<<1,l,mid); 63 build(rt<<1|1,mid+1,r); 64 pushup(rt); 65 } 66 void update(int rt,int l,int r,int x,int k) 67 { 68 if (l==r) 69 { 70 cm[rt]=cs[rt]=k; 71 return; 72 } 73 int mid=(l+r)>>1; 74 if (x<=mid) update(rt<<1,l,mid,x,k); 75 else update(rt<<1|1,mid+1,r,x,k); 76 pushup(rt); 77 } 78 int query_max(int rt,int l,int r,int L,int R) 79 { 80 if (l>=L&&r<=R) 81 { 82 return cm[rt]; 83 } 84 int mid=(l+r)>>1,s=-2e9; 85 if (L<=mid) s=max(s,query_max(rt<<1,l,mid,L,R)); 86 if (R>mid) s=max(s,query_max(rt<<1|1,mid+1,r,L,R)); 87 pushup(rt); 88 return s; 89 } 90 int query_sum(int rt,int l,int r,int L,int R) 91 { 92 if (l>=L&&r<=R) 93 { 94 return cs[rt]; 95 } 96 int mid=(l+r)>>1,s=0; 97 if (L<=mid) s=s+query_sum(rt<<1,l,mid,L,R); 98 if (R>mid) s=s+query_sum(rt<<1|1,mid+1,r,L,R); 99 pushup(rt); 100 return s; 101 } 102 int get_max(int x,int y) 103 { 104 int as=-2e9; 105 while (top[x]!=top[y]) 106 { 107 if (dep[top[x]]<dep[top[y]]) swap(x,y); 108 as=max(as,query_max(1,1,n,dfn[top[x]],dfn[x])); 109 x=fa[top[x]]; 110 } 111 if (dfn[x]>dfn[y]) swap(x,y); 112 as=max(as,query_max(1,1,n,dfn[x],dfn[y])); 113 return as; 114 } 115 int get_sum(int x,int y) 116 { 117 int as=0; 118 while (top[x]!=top[y]) 119 { 120 if (dep[top[x]]<dep[top[y]]) swap(x,y); 121 as=as+query_sum(1,1,n,dfn[top[x]],dfn[x]); 122 x=fa[top[x]]; 123 } 124 if (dfn[x]>dfn[y]) swap(x,y); 125 as=as+query_sum(1,1,n,dfn[x],dfn[y]); 126 return as; 127 } 128 int main() 129 {int i,u,v,x,y; 130 cin>>n; 131 for (i=1;i<=n-1;i++) 132 { 133 scanf("%d%d",&u,&v); 134 add(u,v);add(v,u); 135 } 136 for (i=1;i<=n;i++) 137 scanf("%d",&w[i]); 138 dfs1(1,0);dfs2(1,0,1); 139 build(1,1,n); 140 cin>>q; 141 while (q--) 142 { 143 scanf("%s",s); 144 if (s[0]=='C') 145 { 146 scanf("%d%d",&x,&y); 147 w[x]=y; 148 update(1,1,n,dfn[x],y); 149 } 150 else if (s[1]=='M') 151 { 152 scanf("%d%d",&x,&y); 153 printf("%d\n",get_max(x,y)); 154 } 155 else 156 { 157 scanf("%d%d",&x,&y); 158 printf("%d\n",get_sum(x,y)); 159 } 160 } 161 }