[Bzoj1036][ZJOI2008]树的统计Count

来源:互联网 发布:知有儿童挑促织挑意思 编辑:程序博客网 时间:2024/04/19 11:29
#include<iostream>#include<cstring>#include<cstdio>#define inf 0x7fffffff#define N 30001#define M 60001using namespace std;int n,q,fa[N][15],v[N],deep[N],size[N],head[N],tot,sz,pos[N],belong[N];bool vis[N];struct data{int to,next;}e[M];struct seg{int l,r,mx,sum;}tr[100001];void ins(int u,int v){e[++tot].to=v;e[tot].next=head[u];head[u]=tot;e[++tot].to=u;e[tot].next=head[v];head[v]=tot;}void init(){scanf("%d",&n);for(int i=1;i<=n-1;i++){int a,b;scanf("%d%d",&a,&b);ins(a,b);}for(int i=1;i<=n;i++)scanf("%d",&v[i]);}void dfs1(int x){size[x]=1;vis[x]=1;for(int i=1;i<=14;i++){if(deep[x]<(1<<i))break;fa[x][i]=fa[fa[x][i-1]][i-1];}for(int i=head[x];i;i=e[i].next){if(vis[e[i].to])continue;deep[e[i].to]=deep[x]+1;fa[e[i].to][0]=x;dfs1(e[i].to);size[x]+=size[e[i].to];}}void dfs2(int x,int chain){int k=0;pos[x]=++sz;belong[x]=chain;for(int i=head[x];i;i=e[i].next)if(deep[e[i].to]>deep[x]&&size[e[i].to]>size[k])k=e[i].to;if(!k)return;dfs2(k,chain);for(int i=head[x];i;i=e[i].next)if(deep[e[i].to]>deep[x]&&e[i].to!=k)dfs2(e[i].to,e[i].to);}int lca(int x,int y){if(deep[x]<deep[y])swap(x,y);int t=deep[x]-deep[y];for(int i=0;i<=14;i++)if(t&(1<<i))x=fa[x][i];for(int i=14;i>=0;i--)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];if(x==y)return x;else return fa[x][0];}void build(int k,int l,int r){tr[k].l=l;tr[k].r=r;if(l==r)return;int mid=(l+r)>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);}void update(int k,int x,int y){int l=tr[k].l,r=tr[k].r;if(l==r){tr[k].mx=tr[k].sum=y;return;}int mid=(l+r)>>1;if(x<=mid)update(k<<1,x,y);else if(x>mid)update(k<<1|1,x,y);tr[k].sum=tr[k<<1].sum+tr[k<<1|1].sum;tr[k].mx=max(tr[k<<1].mx,tr[k<<1|1].mx);}int getsum(int k,int x,int y){int l=tr[k].l,r=tr[k].r;if(l==x&&r==y)return tr[k].sum;int mid=(l+r)>>1;if(y<=mid)return getsum(k<<1,x,y);else if(x>mid)return getsum(k<<1|1,x,y);else return getsum(k<<1,x,mid)+getsum(k<<1|1,mid+1,y);}int getmax(int k,int x,int y){int l=tr[k].l,r=tr[k].r;if(l==x&&r==y)return tr[k].mx;int mid=(l+r)>>1;if(y<=mid)return getmax(k<<1,x,y);else if(x>mid)return getmax(k<<1|1,x,y);else return max(getmax(k<<1,x,mid),getmax(k<<1|1,mid+1,y));}int asksum(int x,int y){int sum=0;while(belong[x]!=belong[y]){sum+=getsum(1,pos[belong[x]],pos[x]);x=fa[belong[x]][0];}sum+=getsum(1,pos[y],pos[x]);return sum;}int askmax(int x,int y){int mx=-inf;while(belong[x]!=belong[y]){mx=max(mx,getmax(1,pos[belong[x]],pos[x]));x=fa[belong[x]][0];}mx=max(mx,getmax(1,pos[y],pos[x]));return mx;}void solve(){build(1,1,n);for(int i=1;i<=n;i++)update(1,pos[i],v[i]);scanf("%d",&q);char oper[6];for(int i=1;i<=q;i++){int a,b;scanf("%s%d%d",oper,&a,&b);if(oper[1]=='H')v[a]=b,update(1,pos[a],b);else{int t=lca(a,b);if(oper[1]=='M')printf("%d\n",max(askmax(a,t),askmax(b,t)));else printf("%d\n",asksum(a,t)+asksum(b,t)-v[t]);}}}int main(){init();dfs1(1);dfs2(1,1);solve();return 0;}

0 0