数链剖分(Aragorn's Story )

题目链接:https://vjudge.net/contest/279350#problem/A

题目大意:n个点,m条边,然后q次询问,因为在树上,两个点能确定一条直线,我们可以对这条直线上的所有值进行加减操作,也可以单点询问。

各个数组的作用:sto是刚开始的输入数据,head是前向星,dfsnum指的是dfs序,depth指的是每个点的深度son指的是每个节点的重儿子,father指的是每个点的父节点,Size指的是以当前点为根节点的树,ord指的是遍历顺序,cost指的是编号之后的每个点,top指的是当前的这条重链的最顶端的那个点,剩下的就是线段树的数组了。

注意点:我们通过两个dfs来给这些数组赋值,通过第一个dfs,我们可以把depth和father,size,son求出来,剩下的ord和top通过第二个dfs求出来,为什么使用两个dfs?我的理解就是,第一个dfs和第二个dfs的遍历条件并不相同,第一个dfs就是能走就走,第二个dfs是在按照已经分好链的前提下进行走的,也就是说这里的ord数组并不能在第一个dfs中实现,只能在第二个数组中实现。(后续有新的理解会继续补充)。

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 = 5e4+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],lazy[maxn<<2];
 18 struct node
 19 {
 20     int to;
 21     int nex;
 22 } edge[maxn<<2];
 23 void addedge(int fr,int to)
 24 {
 25     edge[edgnum].nex=head[fr];
 26     edge[edgnum].to=to;
 27     head[fr]=edgnum++;
 28 }
 29 void dfs1(int fr,int rt,int dep)
 30 {
 31     father[fr]=rt;
 32     Size[fr]=1;
 33     son[fr]=-1;
 34     depth[fr]=dep;
 35     for(int i=head[fr]; i!=-1; i=edge[i].nex)
 36     {
 37         int to=edge[i].to;
 38         if(to==rt)
 39             continue;
 40         dfs1(to,fr,dep+1);
 41         Size[fr]+=Size[to];
 42         if(son[to]==-1||(Size[son[fr]]<Size[to]))
 43         {
 44             son[fr]=to;
 45         }
 46     }
 47 }
 48 void dfs2(int fr,int rt)
 49 {
 50     ord[fr]=++dfsnum;
 51     cost[ord[fr]]=sto[fr];
 52     top[fr]=rt;
 53     if(son[fr]!=-1)
 54         dfs2(son[fr],rt);
 55     for(int i=head[fr]; i!=-1; i=edge[i].nex)
 56     {
 57         int u=edge[i].to;
 58         if(son[fr]!=u&&father[fr]!=u)
 59         {
 60             dfs2(u,u);
 61         }
 62     }
 63 }
 64 void init()
 65 {
 66     dfsnum=0;
 67     dfs1(1,-1,1);
 68     dfs2(1,1);
 69 }
 70 void up(int rt)
 71 {
 72     tree[rt]=tree[rt<<1]+tree[rt<<1|1];
 73 }
 74 void down(int len,int rt)
 75 {
 76     if(lazy[rt])
 77     {
 78         lazy[rt<<1]+=lazy[rt];
 79         lazy[rt<<1|1]+=lazy[rt];
 80         tree[rt<<1]+=(len-len/2)*lazy[rt];
 81         tree[rt<<1|1]+=(len/2)*lazy[rt];
 82         lazy[rt]=0;
 83     }
 84 }
 85 void buildtree(int l,int r,int rt)
 86 {
 87     lazy[rt]=0;
 88     tree[rt]=0;
 89     if(l==r)
 90     {
 91         tree[rt]=cost[l];
 92         return ;
 93     }
 94     int m=(l+r)>>1;
 95     buildtree(lson);
 96     buildtree(rson);
 97     up(rt);
 98 }
 99 void update(int l,int r,int rt,int L,int R,int p)
100 {
101     if(L<=l&&R>=r)
102     {
103         tree[rt]+=p*(r-l+1);
104         lazy[rt]+=p;
105         return ;
106     }
107     down(r-l+1,rt);
108     int m=(l+r)>>1;
109     if(L<=m)
110         update(lson,L,R,p);
111     if(R>m)
112         update(rson,L,R,p);
113     up(rt);
114 }
115 void Update(int n,int x,int y,int p)
116 {
117     int tx=top[x],ty=top[y];
118     while(tx!=ty)
119     {
120         if(depth[tx]<depth[ty])
121         {
122             swap(tx,ty);
123             swap(x,y);
124         }
125         update(1,n,1,ord[tx],ord[x],p);
126         x=father[tx],tx=top[x];
127     }
128     if(depth[x]<depth[y])
129     {
130         swap(x,y);
131     }
132     update(1,n,1,ord[y],ord[x],p);
133 }
134 int query(int l,int r,int rt,int pos)
135 {
136     if(l==r)
137     {
138         return tree[rt];
139     }
140     down(r-l+1,rt);
141     int ans=0;
142     int m=(l+r)>>1;
143     if(pos<=m)
144         ans+=query(lson,pos);
145     if(pos>m)
146         ans+=query(rson,pos);
147     return ans;
148     up(rt);
149 }
150 int main()
151 {
152     int n,m,q;
153     while(~scanf("%d %d %d",&n,&m,&q))
154     {
155         edgnum=0;
156         for(int i=1; i<=n; i++)
157         {
158             scanf("%d",&sto[i]);
159             head[i]=-1;
160         }
161         int t1,t2;
162         for(int i=1; i<=m; i++)
163         {
164             scanf("%d %d",&t1,&t2);
165             addedge(t1,t2);
166             addedge(t2,t1);
167         }
168         init();
169         char str[10];
170         buildtree(1,n,1);
171         int t3;
172         while(q--)
173         {
174             scanf("%s",str);
175             if(str[0]=='I')
176             {
177                 scanf("%d %d %d",&t1,&t2,&t3);
178                 Update(n,t1,t2,t3);
179             }
180             else if(str[0]=='Q')
181             {
182                 scanf("%d",&t1);
183                 int ans=query(1,n,1,ord[t1]);
184                 printf("%d
",ans);
185             }
186             else if(str[0]=='D')
187             {
188                 scanf("%d %d %d",&t1,&t2,&t3);
189                 Update(n,t1,t2,-t3);
190             }
191         }
192     }
193     return 0;
194 }
原文地址:https://www.cnblogs.com/letlifestop/p/10284125.html