题目
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
分析
- 解法一:(我打错了)跑一遍dfs序,将点映射到mapp里
- 然后用线段树维护值
- 每一次将值扔到线段树里查找
- 解法二:树剖模板题
代码
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define ll long long 5 using namespace std; 6 int n,m; 7 int flag[30001],t[30001],h[30001]; 8 int id[30001],fa[30010],son[30001],top[30001],dep[30001]; 9 int mapp[30001],li[30001],siz[30001]; 10 struct sb 11 { 12 int l,r; 13 ll val; 14 }tr[30001*4]; 15 int cnt=0; 16 struct node{ 17 int u,v,nx; 18 }g[300011*2]; 19 void add(int u,int v) { g[++cnt].u=u; g[cnt].v=v; g[cnt].nx=li[u]; li[u]=cnt; 20 g[++cnt].u=v; g[cnt].v=u; g[cnt].nx=li[v]; li[v]=cnt; } 21 void dfs1(int u) 22 { 23 int mxsiz=0,mxid=0; 24 siz[u]=1; 25 for (int i=li[u];i;i=g[i].nx) 26 { 27 int v=g[i].v; 28 if (v!=fa[u]) 29 { 30 fa[v]=u,dep[v]=dep[u]+1,dfs1(v),siz[u]+=siz[v]; 31 if (siz[v]>mxsiz) mxsiz=siz[v],mxid=v; 32 } 33 } 34 son[u]=mxid; 35 } 36 int tot; 37 void dfs2(int u,int p) 38 { 39 top[u]=p,id[u]=++tot; 40 if(son[u]) dfs2(son[u],p); 41 for (int i=li[u];i;i=g[i].nx) 42 { 43 int v=g[i].v; 44 if (v!=fa[u]&&v!=son[u]) 45 dfs2(v,v); 46 } 47 } 48 void build(int k,int a,int b) 49 { 50 tr[k].l=a; tr[k].r=b; 51 if (a==b) return; 52 int mid=a+b>>1; 53 build(k<<1,a,mid); 54 build(k<<1|1,mid+1,b); 55 } 56 void ins(int k,int x,int w) 57 { 58 if (tr[k].l==tr[k].r&&tr[k].l==x) 59 { 60 tr[k].val=w; 61 return; 62 } 63 int mid=(tr[k].l+tr[k].r)>>1; 64 if (x<=mid) ins(k<<1,x,w); 65 else ins(k<<1|1,x,w); 66 tr[k].val=tr[k<<1|1].val+tr[k<<1].val; 67 } 68 ll find(int k,int ql, int qr) 69 { 70 if (ql<=tr[k].l&&tr[k].r<=qr) return tr[k].val; 71 int mid=tr[k].l+tr[k].r>>1; ll ret=0; 72 if (ql<=mid) ret+=find(k<<1,ql,qr); 73 if (mid+1<=qr) ret+=find(k<<1|1,ql,qr); 74 return ret; 75 } 76 int main () 77 { 78 cin>>n>>m; 79 for (int i=1,x,y;i<=n-1;i++) 80 { 81 scanf("%d %d",&x,&y); 82 add(x,y); 83 } 84 dfs1(1); 85 dfs2(1,1); 86 build(1,1,n); 87 for (int i=1,u;i<=n;i++) 88 scanf("%d",&u),ins(1,id[i],u); 89 for (int i=1,k,a,b;i<=m;i++) 90 { 91 scanf("%d %d %d",&k,&a,&b); 92 if (k==1) ins(1,id[a],b); 93 else 94 { 95 ll ans=0; 96 while (top[a]!=top[b]) 97 { 98 if (dep[top[a]]<dep[top[b]]) swap(a,b); 99 ans+=find(1,id[top[a]],id[a]); 100 a=fa[top[a]]; 101 } 102 if (dep[a]<dep[b]) swap(a,b); 103 ans+=find(1,id[b],id[a]); 104 printf("%lld\n",ans); 105 } 106 } 107 }