题目链接:https://vjudge.net/contest/279350#problem/B
题目大意:给你n,q,s。n指的是有n个点,q代表有q次询问,s代表的是起点。然后接下来会有n-1条边,双向边,带有权值,对于q次询问,如果输入的第一个数是1,然后接下来会输入两个数,t1,t2。t带边将第t1条边的权值改成t2.如果第一个数是0,接下来会输入一个t,询问从s到t的花费。
具体思路:对于边权,我们可以改成点权,这条边的权值赋给这条边上深度大的那条边,然后就是单点更新和区间查询了。
AC代码:
1 #include<iostream> 2 #include<cmath> 3 #include<stack> 4 #include<queue> 5 #include<stdio.h> 6 #include<string> 7 #include<cstring> 8 #include<algorithm> 9 using namespace std; 10 # define inf 0x3f3f3f3f 11 # define ll long long 12 # define lson l,m,rt<<1 13 # define rson m+1,r,rt<<1|1 14 const int maxn = 1e5+100; 15 int sto[maxn],head[maxn],edgnum,dfsnum,depth[maxn]; 16 int son[maxn],father[maxn],Size[maxn],ord[maxn],cost[maxn],top[maxn]; 17 int tree[maxn<<2]; 18 struct node 19 { 20 int fr; 21 int to; 22 int nex; 23 int cost; 24 } edge[maxn<<2],po[maxn<<2]; 25 void addedge(int fr,int to) 26 { 27 edge[edgnum].fr=fr; 28 edge[edgnum].to=to; 29 edge[edgnum].nex=head[fr]; 30 head[fr]=edgnum++; 31 } 32 void dfs1(int fr,int rt,int dep) 33 { 34 father[fr]=rt; 35 Size[fr]=1; 36 son[fr]=-1; 37 depth[fr]=dep; 38 for(int i=head[fr]; i!=-1; i=edge[i].nex) 39 { 40 int to=edge[i].to; 41 if(to==rt) 42 continue; 43 dfs1(to,fr,dep+1); 44 Size[fr]+=Size[to]; 45 if(son[to]==-1||(Size[son[fr]]<Size[to])) 46 { 47 son[fr]=to; 48 } 49 } 50 } 51 void dfs2(int fr,int rt) 52 { 53 ord[fr]=++dfsnum; 54 cost[ord[fr]]=sto[fr]; 55 top[fr]=rt; 56 if(son[fr]!=-1) 57 dfs2(son[fr],rt); 58 for(int i=head[fr]; i!=-1; i=edge[i].nex) 59 { 60 int u=edge[i].to; 61 if(son[fr]!=u&&father[fr]!=u) 62 { 63 dfs2(u,u); 64 } 65 } 66 } 67 void up(int rt) 68 { 69 tree[rt]=tree[rt<<1]+tree[rt<<1|1]; 70 } 71 void buildtree(int l,int r,int rt) 72 { 73 if(l==r) 74 { 75 tree[rt]=sto[l]; 76 return ; 77 } 78 int m=(l+r)>>1; 79 buildtree(lson); 80 buildtree(rson); 81 up(rt); 82 } 83 int query(int l,int r,int rt,int L,int R) 84 { 85 if(L<=l&&R>=r) 86 { 87 return tree[rt]; 88 } 89 int ans=0; 90 int m=(l+r)>>1; 91 if(L<=m) 92 ans+=query(lson,L,R); 93 if(R>m) 94 ans+=query(rson,L,R); 95 up(rt); 96 return ans; 97 } 98 void update(int l,int r,int rt,int pos,int p) 99 { 100 if(l==r) 101 { 102 tree[rt]=p; 103 return ; 104 } 105 int m=(l+r)>>1; 106 if(pos<=m) 107 update(lson,pos,p); 108 if(pos>m) 109 update(rson,pos,p); 110 up(rt); 111 } 112 int Query(int n,int x,int y) 113 { 114 int tx=top[x],ty=top[y]; 115 int ans=0; 116 while(tx!=ty) 117 { 118 if(depth[tx]<depth[ty]) 119 { 120 swap(tx,ty); 121 swap(x,y); 122 } 123 ans+=query(1,n,1,ord[tx],ord[x]); 124 x=father[tx],tx=top[x]; 125 } 126 if(depth[x]<depth[y]) 127 { 128 swap(x,y); 129 } 130 return ans+query(1,n,1,ord[y]+1,ord[x]);//这个地方注意应该是ord[y]+1,如果我们询问的是从3->5的,有可能3这个点是另一条边的权值,所以应该把点往下移动一个。 131 } 132 int main() 133 { 134 int n,q,s; 135 scanf("%d %d %d",&n,&q,&s); 136 int t1,t2,t3; 137 memset(head,-1,sizeof(head)); 138 for(int i=1; i<=n-1; i++) 139 { 140 scanf("%d %d %d",&t1,&t2,&t3); 141 addedge(t1,t2); 142 addedge(t2,t1); 143 po[i].fr=t1; 144 po[i].to=t2; 145 po[i].cost=t3; 146 } 147 dfs1(1,-1,1); 148 dfs2(1,1); 149 for(int i=1; i<=n-1; i++) 150 { 151 t1=depth[po[i].fr]; 152 t2=depth[po[i].to]; 153 if(t1>t2) 154 { 155 swap(po[i].fr,po[i].to); 156 } 157 update(1,n,1,ord[po[i].to],po[i].cost); 158 } 159 while(q--) 160 { 161 162 scanf("%d",&t1); 163 if(t1==0) 164 { 165 scanf("%d",&t2); 166 int ans=Query(n,s,t2); 167 printf("%d\n",ans); 168 s=t2; 169 } 170 else 171 { 172 scanf("%d %d",&t1,&t2); 173 update(1,n,1,ord[po[t1].to],t2); 174 } 175 } 176 return 0; 177 }