数链剖分(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 }

 

posted @ 2019-01-18 08:19  Let_Life_Stop  阅读(322)  评论(0编辑  收藏  举报