树剖+线段树
据说是入门题,然而蒟蒻没有做过。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 #define re register int 3 #define maxn 100000+5 4 #define inf 1000000000 5 #define lson now<<1 6 #define rson now<<1|1 7 using namespace std; 8 inline int read() 9 { 10 int x=0,f=1; 11 char ch=getchar(); 12 while(!isdigit(ch)) 13 { 14 if(ch=='-') f=-1; 15 ch=getchar(); 16 } 17 while(isdigit(ch)) 18 { 19 x=x*10+ch-'0'; 20 ch=getchar(); 21 } 22 return x*f; 23 } 24 inline void write(int x) 25 { 26 if(x<0) putchar('-'),x=-x; 27 if(x>9) write(x/10); 28 putchar(x%10+'0'); 29 } 30 int dep[maxn],siz[maxn],son[maxn],fa[maxn]; 31 int id[maxn],rnk[maxn],top[maxn],val[maxn]; 32 int n; 33 struct edge{ 34 int nex,to; 35 }ed[maxn<<1]; 36 int head[maxn]; 37 struct tree{ 38 int sum,maxw; 39 }tr[maxn<<2]; 40 void pushup(int now) 41 { 42 tr[now].sum=tr[lson].sum+tr[rson].sum; 43 tr[now].maxw=max(tr[lson].maxw,tr[rson].maxw); 44 } 45 void build(int now,int l,int r) 46 { 47 if(l==r) 48 { 49 tr[now].sum=tr[now].maxw=val[rnk[l]]; 50 return; 51 } 52 int mid=(l+r)>>1; 53 build(lson,l,mid); 54 build(rson,mid+1,r); 55 pushup(now); 56 } 57 int qsum(int ql,int qr,int l,int r,int now) 58 { 59 if(l>=ql&&r<=qr) return tr[now].sum; 60 int mid=(l+r)>>1,res=0; 61 if(ql<=mid) res+=qsum(ql,qr,l,mid,lson); 62 if(qr>mid) res+=qsum(ql,qr,mid+1,r,rson); 63 return res; 64 } 65 int qmax(int ql,int qr,int l,int r,int now) 66 { 67 if(l>=ql&&r<=qr) return tr[now].maxw; 68 int mid=(l+r)>>1; 69 int Max=-inf; 70 if(ql<=mid) Max=max(Max,qmax(ql,qr,l,mid,lson)); 71 if(qr>mid) Max=max(Max,qmax(ql,qr,mid+1,r,rson)); 72 return Max; 73 } 74 void update(int l,int r,int now,int ch,int w) 75 { 76 if(l==r) 77 { 78 tr[now].sum=tr[now].maxw=w; 79 return; 80 } 81 int mid=(l+r)>>1; 82 if(ch<=mid) 83 update(l,mid,lson,ch,w); 84 else 85 update(mid+1,r,rson,ch,w); 86 pushup(now); 87 } 88 int cnt,num,q; 89 void add(int x,int y) 90 { 91 ed[++cnt].nex=head[x]; 92 ed[cnt].to=y; 93 head[x]=cnt; 94 } 95 void dfs(int pos,int f) 96 { 97 fa[pos]=f; 98 dep[pos]=dep[f]+1; 99 siz[pos]=1; 100 for(re i=head[pos];i;i=ed[i].nex) 101 { 102 if(ed[i].to!=f){ 103 dfs(ed[i].to,pos); 104 siz[pos]+=siz[ed[i].to]; 105 if(siz[ed[i].to]>siz[son[pos]]) 106 son[pos]=ed[i].to; 107 } 108 } 109 } 110 void dfs2(int pos,int tp) 111 { 112 top[pos]=tp; 113 id[pos]=++num; 114 rnk[num]=pos; 115 if(son[pos]) dfs2(son[pos],tp); 116 for(re i=head[pos];i;i=ed[i].nex) 117 if(ed[i].to!=fa[pos]&&ed[i].to!=son[pos]) 118 dfs2(ed[i].to,ed[i].to); 119 } 120 int qqsum(int x,int y) 121 { 122 int res=0; 123 while(top[x]!=top[y]){ 124 if(dep[top[x]]<dep[top[y]]) swap(x,y); 125 res+=qsum(id[top[x]],id[x],1,n,1); 126 x=fa[top[x]]; 127 } 128 if(dep[x]>dep[y]) swap(x,y); 129 res+=qsum(id[x],id[y],1,n,1); 130 return res; 131 } 132 int qqmax(int x,int y) 133 { 134 int Max=-inf; 135 while(top[x]!=top[y]){ 136 if(dep[top[x]]<dep[top[y]]) swap(x,y); 137 Max=max(Max,qmax(id[top[x]],id[x],1,n,1)); 138 x=fa[top[x]]; 139 } 140 if(dep[x]>dep[y]) swap(x,y); 141 Max=max(Max,qmax(id[x],id[y],1,n,1)); 142 return Max; 143 } 144 int main() 145 { 146 n=read(); 147 for(re i=1;i<=n-1;i++) 148 { 149 int x,y; 150 x=read(); 151 y=read(); 152 add(x,y); 153 add(y,x); 154 } 155 for(re i=1;i<=n;i++) 156 val[i]=read(); 157 dfs(1,0); 158 dfs2(1,1); 159 build(1,1,n); 160 q=read(); 161 char s[10]; 162 while(q--) 163 { 164 int x,y; 165 cin>>s; 166 x=read(); 167 y=read(); 168 if(s[0]=='C') update(1,n,1,id[x],y); 169 else if(s[1]=='M') 170 { 171 write(qqmax(x,y)); 172 putchar(' '); 173 } 174 else{ 175 write(qqsum(x,y)); 176 putchar(' '); 177 } 178 } 179 return 0; 180 }