题目链接:http://poj.org/problem?id=2763
题意:
给定一棵含n个结点的树和树的边权,共有q次操作,分为两种
0 c :求从位置s到c的距离,然后s变成c
1 a b:把第a条边的权值变为b
分析:
树链剖分,注意查询后要改变起点
代码如下:
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 6 using namespace std; 7 const int maxn=110000; 8 9 struct Edge 10 { 11 int to,next; 12 }edge[maxn*2]; 13 int head[maxn]; 14 int cnt,tmp,n; 15 int dep[maxn],fa[maxn],size[maxn],son[maxn],top[maxn],id[maxn],rank[maxn]; 16 struct Node 17 { 18 int u,v,c; 19 }node[maxn]; 20 21 void init() 22 { 23 memset(head,-1,sizeof(head)); 24 memset(son,-1,sizeof(son)); 25 tmp=0; 26 cnt=0; 27 } 28 29 void addedge(int u,int v) 30 { 31 edge[cnt].to=v; 32 edge[cnt].next=head[u]; 33 head[u]=cnt++; 34 } 35 36 void dfs_1(int u,int f,int d) 37 { 38 dep[u]=d; 39 size[u]=1; 40 fa[u]=f; 41 for(int i=head[u];i!=-1;i=edge[i].next) 42 { 43 int v=edge[i].to; 44 if(v==f) 45 continue; 46 dfs_1(v,u,d+1); 47 size[u]+=size[v]; 48 if(son[u]==-1||size[son[u]]<size[v]) 49 son[u]=v; 50 } 51 } 52 53 void dfs_2(int u,int tp) 54 { 55 top[u]=tp; 56 id[u]=++tmp; 57 rank[tmp]=u; 58 if(son[u]!=-1) 59 dfs_2(son[u],tp); 60 for(int i=head[u];i!=-1;i=edge[i].next) 61 { 62 int v=edge[i].to; 63 if(v!=fa[u]&&v!=son[u]) 64 dfs_2(v,v); 65 } 66 } 67 struct Tree 68 { 69 int left,right; 70 int t; 71 }tree[maxn*4]; 72 73 void pushup(int i) 74 { 75 tree[i].t=tree[i*2].t+tree[i*2+1].t; 76 } 77 78 void build(int i,int begin,int end) 79 { 80 tree[i].left=begin; 81 tree[i].right=end; 82 tree[i].t=0; 83 if(begin==end) 84 return; 85 int mid=(begin+end)/2; 86 build(i*2,begin,mid); 87 build(i*2+1,mid+1,end); 88 } 89 90 void update(int i,int k,int val) 91 { 92 if(tree[i].left==k&&tree[i].right==k) 93 { 94 tree[i].t=val; 95 return; 96 } 97 int mid=(tree[i].left+tree[i].right)/2; 98 if(k<=mid) 99 update(i*2,k,val); 100 else 101 update(i*2+1,k,val); 102 pushup(i); 103 } 104 105 int query(int i,int begin,int end) 106 { 107 if(tree[i].left>=begin&&tree[i].right<=end) 108 return tree[i].t; 109 int mid=(tree[i].left+tree[i].right)/2; 110 int res=0; 111 if(mid>=begin) 112 res+=query(i*2,begin,end); 113 if(mid<end) 114 res+=query(i*2+1,begin,end); 115 return res; 116 } 117 118 int find(int u,int v) 119 { 120 int tp1=top[u],tp2=top[v]; 121 int res=0; 122 while(tp1!=tp2) 123 { 124 if(dep[tp1]<dep[tp2]) 125 { 126 swap(tp1,tp2); 127 swap(u,v); 128 } 129 res+=query(1,id[tp1],id[u]); 130 u=fa[tp1]; 131 tp1=top[u]; 132 } 133 if(u==v) 134 return res; 135 if(dep[u]>dep[v]) 136 swap(u,v); 137 res+=query(1,id[son[u]],id[v]); 138 return res; 139 } 140 141 int main() 142 { 143 int n,q,s; 144 scanf("%d%d%d",&n,&q,&s); 145 init(); 146 for(int i=1;i<n;i++) 147 { 148 scanf("%d%d%d",&node[i].u,&node[i].v,&node[i].c); 149 addedge(node[i].u,node[i].v); 150 addedge(node[i].v,node[i].u); 151 } 152 dfs_1(1,0,1); 153 dfs_2(1,1); 154 build(1,1,tmp); 155 for(int i=1;i<n;i++) 156 { 157 if(dep[node[i].u]>dep[node[i].v]) 158 swap(node[i].u,node[i].v); 159 update(1,id[node[i].v],node[i].c); 160 } 161 for(int i=0;i<q;i++) 162 { 163 int a,k,w; 164 scanf("%d",&a); 165 if(a==0) 166 { 167 scanf("%d",&k); 168 printf("%d ",find(s,k)); 169 s=k; 170 } 171 else 172 { 173 scanf("%d%d",&k,&w); 174 update(1,id[node[k].v],w); 175 } 176 } 177 return 0; 178 }