数链剖分(Housewife Wind )
题目链接: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 }