poj 2763 Housewife Wind (树链剖分)

题目链接: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\n",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 }

 

posted @ 2016-03-23 15:11  邀月独斟  阅读(523)  评论(1编辑  收藏  举报