【bzoj1036】[ZJOI2008]树的统计Count
题意:
I. CHANGE u t : 把结点u的权值改为t
II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值
III. QSUM u v: 询问从点u到点v的路径上的节点的权值和
树链剖分
siz[v]表示以v为根的子树的节点数
top[v]表示v所在的重链的顶端节点
fa[v]表示v的父亲
son[v]表示与v在同一重链上的v的儿子节点
pos[v]表示v与其父亲节点的连边在线段树中的位置
1 #include<algorithm> 2 #include<iostream> 3 #include<cstdlib> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 using namespace std; 8 9 typedef long long LL; 10 11 #define INF 0x7fffffff 12 #define N 30010 13 14 struct Node 15 { 16 LL maxn,sum; 17 }tr[N<<2]; 18 19 struct edge 20 { 21 int to,next; 22 }e[N<<2]; 23 24 int cnt,head[N<<2]; 25 26 int id,siz[N],top[N],fa[N],son[N]; 27 int d[N],pos[N],v[N]; 28 29 char s[15]; 30 31 int n,m; 32 int a,b; 33 34 LL ans,sum; 35 36 void link(int x,int y) 37 { 38 e[++cnt]=(edge){y,head[x]}; 39 head[x]=cnt; 40 } 41 42 void dfs(int x,int y) 43 { 44 siz[x]=1; 45 fa[x]=y; 46 d[x]=d[y]+1; 47 int k=0; 48 for (int i=head[x];i;i=e[i].next) 49 if (e[i].to!=fa[x]) 50 { 51 dfs(e[i].to,x); 52 siz[x]+=siz[e[i].to]; 53 if (siz[e[i].to]>k) 54 k=siz[e[i].to],son[x]=e[i].to; 55 } 56 } 57 58 void dfs2(int x,int y) 59 { 60 top[x]=y; 61 pos[x]=++id; 62 if (!son[x]) 63 return ; 64 dfs2(son[x],y); 65 for (int i=head[x];i;i=e[i].next) 66 if (e[i].to!=fa[x] && e[i].to!=son[x]) 67 dfs2(e[i].to,e[i].to); 68 } 69 70 void pushup(int now) 71 { 72 tr[now].sum=tr[now<<1].sum+tr[now<<1|1].sum; 73 tr[now].maxn=max(tr[now<<1].maxn,tr[now<<1|1].maxn); 74 } 75 76 void update(int nowl,int nowr,int now,int x,int y) 77 { 78 if (nowl==nowr) 79 { 80 tr[now].sum=y; 81 tr[now].maxn=y; 82 return ; 83 } 84 int mid=(nowl+nowr)>>1; 85 if (x<=mid) 86 update(nowl,mid,now<<1,x,y); 87 else 88 update(mid+1,nowr,now<<1|1,x,y); 89 pushup(now); 90 } 91 92 void query(int nowl,int nowr,int now,int x,int y) 93 { 94 if (nowl==x && nowr==y) 95 { 96 ans=max(ans,tr[now].maxn); 97 sum+=tr[now].sum; 98 return ; 99 } 100 int mid=(nowl+nowr)>>1; 101 if (y<=mid) 102 query(nowl,mid,now<<1,x,y); 103 else if (x>mid) 104 query(mid+1,nowr,now<<1|1,x,y); 105 else 106 query(nowl,mid,now<<1,x,mid),query(mid+1,nowr,now<<1|1,mid+1,y); 107 } 108 109 void find(int x,int y) 110 { 111 int f1=top[x],f2=top[y]; 112 ans=-INF; 113 sum=0; 114 while (f1!=f2) 115 { 116 if (d[f1]<d[f2]) 117 swap(f1,f2),swap(x,y); 118 query(1,n,1,pos[f1],pos[x]); 119 x=fa[f1]; 120 f1=top[x]; 121 } 122 if (d[x]>d[y]) 123 swap(x,y); 124 query(1,n,1,pos[x],pos[y]); 125 } 126 127 int main() 128 { 129 scanf("%d",&n); 130 for (int i=1;i<n;i++) 131 { 132 scanf("%d%d",&a,&b); 133 link(a,b); 134 link(b,a); 135 } 136 for (int i=1;i<=n;i++) 137 scanf("%d",&v[i]); 138 d[1]=1; 139 dfs(1,0); 140 dfs2(1,1); 141 for (int i=1;i<=n;i++) 142 update(1,n,1,pos[i],v[i]); 143 scanf("%d",&m); 144 int x,y; 145 while (m--) 146 { 147 scanf("%s%d%d",s,&x,&y); 148 if (s[0]=='C') 149 update(1,n,1,pos[x],y); 150 else 151 { 152 find(x,y); 153 if (s[1]=='M') 154 printf("%lld\n",ans); 155 else 156 printf("%lld\n",sum); 157 } 158 } 159 return 0; 160 } 161