题目链接:传送门
题目大意:给你一棵树,小明起点在一个节点上,然后每条边有权值,有两种操作。
0 X叫小明从当前节点到 X,花费为路径上权值和。
1 X V 表示把 按输入顺序中第 X 条边的权值变为 V
对于每个操作 0,输出对应的花费。
题目思路:树链剖分
对于这种边上有权值但是是查找点对的题目,可以把边上的权值相应的赋值给对
应的深度较深的节点。查找时最后一次的操作需要把 id[x]+1,因为此时id[x]
对应的边不用经过。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cmath> 5 #include <algorithm> 6 #include <cstring> 7 #include <stack> 8 #include <cctype> 9 #include <queue> 10 #include <string> 11 #include <vector> 12 #include <set> 13 #include <map> 14 #include <climits> 15 #define lson rt<<1,l,mid 16 #define rson rt<<1|1,mid+1,r 17 #define fi first 18 #define se second 19 #define ping(x,y) ((x-y)*(x-y)) 20 #define mst(x,y) memset(x,y,sizeof(x)) 21 #define mcp(x,y) memcpy(x,y,sizeof(y)) 22 using namespace std; 23 #define gamma 0.5772156649015328606065120 24 #define MOD 1000000007 25 #define inf 0x3f3f3f3f 26 #define N 100001 27 #define maxn 30010 28 typedef pair<int,int> PII; 29 typedef long long LL; 30 LL read(){ 31 LL x=0,f=1;char ch=getchar(); 32 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 33 while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} 34 return x*f; 35 } 36 37 int n,m,k,L,R,S; 38 int seg[N<<2]; 39 int head[N],hcnt; 40 int fa[N]; 41 int son[N]; 42 int siz[N]; 43 int dep[N]; 44 int top[N]; 45 int id[N],tid; 46 int posi[N]; 47 struct Node{int to,nxt;}node[N<<1]; 48 struct Edge{int x,y,v;}edge[N<<1]; 49 50 void init(){ 51 mst(id,0);mst(siz,0);mst(son,0); 52 mst(head,-1);hcnt=tid=0; 53 } 54 void dfs1(int u,int f,int deep){ 55 dep[u]=deep; 56 fa[u]=f; 57 siz[u]=1; 58 for(int i=head[u];~i;i=node[i].nxt){ 59 int e=node[i].to; 60 if(e==f)continue; 61 dfs1(e,u,deep+1); 62 siz[u]+=siz[e]; 63 if(!son[u]||siz[son[u]]<siz[e]) 64 son[u]=e; 65 } 66 } 67 void dfs2(int u,int tp){ 68 top[u]=tp; 69 id[u]=++tid; 70 posi[tid]=u; 71 if(!son[u])return; 72 dfs2(son[u],tp); 73 for(int i=head[u];~i;i=node[i].nxt){ 74 int e=node[i].to; 75 if(!id[e])dfs2(e,e); 76 } 77 } 78 void update(int rt,int l,int r,int v){ 79 if(l==r){seg[rt]=v;return;} 80 int mid=l+r>>1; 81 if(L<=mid)update(lson,v); 82 else update(rson,v); 83 seg[rt]=seg[rt<<1]+seg[rt<<1|1]; 84 } 85 int query(int rt,int l,int r){ 86 if(L<=l&&r<=R)return seg[rt]; 87 int mid=l+r>>1; 88 int temp=0; 89 if(L<=mid)temp+=query(lson); 90 if(R>mid)temp+=query(rson); 91 return temp; 92 } 93 int lca(int x,int y){ 94 int res=0; 95 while(top[x]!=top[y]){ 96 if(dep[top[x]]<dep[top[y]])swap(x,y); 97 L=id[top[x]],R=id[x]; 98 res+=query(1,1,n); 99 x=fa[top[x]]; 100 } 101 if(dep[x]>dep[y])swap(x,y); 102 L=id[x]+1,R=id[y]; 103 res+=query(1,1,n); 104 return res; 105 } 106 inline void addedge(int x,int y,int v){ 107 node[hcnt].to=y,node[hcnt].nxt=head[x],head[x]=hcnt++; 108 node[hcnt].to=x,node[hcnt].nxt=head[y],head[y]=hcnt++; 109 } 110 int main(){ 111 int i,j,group,x,y,v,Case=0; 112 while(scanf("%d",&n)!=EOF){ 113 init(); 114 m=read();S=read(); 115 for(i=1;i<n;++i){ 116 edge[i].x=read();edge[i].y=read();edge[i].v=read(); 117 addedge(edge[i].x,edge[i].y,edge[i].v); 118 } 119 dfs1(1,1,1);dfs2(1,1); 120 mst(seg,0); 121 for(i=1;i<n;++i){ 122 if(dep[edge[i].x]<dep[edge[i].y])swap(edge[i].x,edge[i].y); 123 L=id[edge[i].x]; 124 update(1,1,n,edge[i].v); 125 } 126 while(m--){ 127 y=read();x=read(); 128 if(y==0){ 129 printf("%d ",lca(S,x)); 130 S=x; 131 } 132 else{ 133 v=read(); 134 L=id[edge[x].x]; 135 update(1,1,n,v); 136 } 137 } 138 } 139 return 0; 140 }