Description
已知无向连通图G由N个点,N-1条边组成。每个点有给定权值。现有M个操作,操作分为2种:操作1,将某点权值更改;操作2,询问从点A至点B路径上所有点的权值和。
Input
每个输入文件中仅包含一个测试数据。
第一行包含两个整数N,M。
第二行至第N行每行包含2个整数,A、B,表示节点A与节点B有一条边相连。
第N+1行包含N个整数,表示第N个点的初始权值。
第N+2行至第N+M+1行每行包含三个整数,K、A、B(若K=1,表示将点A权值改为B;若K=2表示询问点A至点B路径上所有点的权值和)
Output
输出文件若干行,分别对应每次操作2的答案。
Sample Input
3 2 1 2 1 3 1 2 3 2 1 3 2 2 3
Sample Output
4 6
Data Constraint
Hint
对于60%的数据,1<=N,M<=1000
对于100%的数据,2<=N<=30000;0<=M<=200000
分析
树剖模板……
#include <iostream> #include <cstdio> #define lson (x<<1) #define rson ((x<<1)+1) using namespace std; const int N=3e4+10; struct Graph { int v,nx; }g[2*N]; int cnt,list[N]; int top[N],sz[N],seg[N],f[N],dep[N],son[N],w[N]; int t[4*N],scnt,rev[N],rt=1; int n,m; void Add(int u,int v) { g[++cnt]=(Graph){v,list[u]};list[u]=cnt; g[++cnt]=(Graph){u,list[v]};list[v]=cnt; } void DFS(int u,int fa) { dep[u]=dep[fa]+1;f[u]=fa;sz[u]=1; for (int i=list[u];i;i=g[i].nx) if (g[i].v!=fa) { DFS(g[i].v,u); sz[u]+=sz[g[i].v]; if (sz[g[i].v]>sz[son[u]]) son[u]=g[i].v; } } void DFS(int u) { int s=son[u]; if (s) { top[s]=top[u]; rev[seg[s]=++scnt]=s; DFS(s); } for (int i=list[u];i;i=g[i].nx) if (!top[g[i].v]) top[g[i].v]=g[i].v,rev[seg[g[i].v]=++scnt]=g[i].v,DFS(g[i].v); } void Update(int x) {t[x]=t[lson]+t[rson];} void Build(int x,int l,int r) { if (l==r) { t[x]=w[rev[l]]; return; } int mid=l+r>>1; Build(lson,l,mid);Build(rson,mid+1,r); Update(x); } void Change(int x,int l,int r,int k,int z) { if (k<l||r<k) return; if (l==r&&l==k) { t[x]=z; return; } int mid=l+r>>1; if (k<=mid) Change(lson,l,mid,k,z); else Change(rson,mid+1,r,k,z); Update(x); } int Query(int x,int l,int r,int ll,int rr) { if (r<l||rr<l||r<ll) return 0; if (ll<=l&&r<=rr) return t[x]; int mid=l+r>>1,ans=0; if (ll<=mid) ans+=Query(lson,l,mid,ll,rr); if (mid<rr) ans+=Query(rson,mid+1,r,ll,rr); return ans; } int Query(int x,int y) { int fx=top[x],fy=top[y],ans=0; while (fx!=fy) { if (dep[fx]<dep[fy]) swap(x,y),swap(fx,fy); ans+=Query(rt,1,scnt,seg[fx],seg[x]); x=f[fx];fx=top[x]; } if (dep[x]<dep[y]) swap(x,y),swap(fx,fy); return ans+Query(rt,1,scnt,seg[y],seg[x]); } int main() { scanf("%d%d",&n,&m); for (int i=1,u,v;i<n;i++) scanf("%d%d",&u,&v),Add(u,v); for (int i=1;i<=n;i++) scanf("%d",&w[i]); DFS(1,0);top[1]=1;rev[seg[1]=++scnt]=1;DFS(1);Build(rt,1,scnt); for (;m;m--) { int k,a,b; scanf("%d%d%d",&k,&a,&b); if (k==1) Change(rt,1,scnt,seg[a],b); else printf("%d\n",Query(a,b)); } }