树链剖分-基于点权

Posted leesongt

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树链剖分-基于点权相关的知识,希望对你有一定的参考价值。

  1 /*
  2   题意:给定一个数,修改u->v路径上的点权,查询每点的值
  3   题解:基于点权
  4   时间:2018.07.18
  5 */
  6 
  7 #include <bits/stdc++.h>
  8 using namespace std;
  9 
 10 typedef long long LL;
 11 const int MAXN = 100005;
 12 const LL MOD7 = 1e9+7;
 13 
 14 struct Edge
 15 {
 16     int u,v;
 17     int next;
 18 }edge[2*MAXN];
 19 int head[MAXN];
 20 int cnt;
 21 
 22 int top[MAXN];
 23 int fa[MAXN];
 24 int deep[MAXN];
 25 int num[MAXN];
 26 int p[MAXN];   //访问序号
 27 int fp[MAXN];  // 访问序号的逆
 28 int son[MAXN]; //重儿子
 29 int pos;
 30 
 31 void init()
 32 {
 33     cnt=0;
 34     memset(head,-1,sizeof(head));
 35     pos=1;
 36     memset(son,-1,sizeof(son));
 37 }
 38 
 39 void addEdge(int u,int v)
 40 {
 41     edge[cnt].u=u;edge[cnt].v=v;edge[cnt].next=head[u];head[u]=cnt++;
 42 }
 43 
 44 void dfs1(int u,int pre,int depth)
 45 {
 46     num[u]=1;
 47     fa[u]=pre;
 48     deep[u]=depth;
 49     for (int i=head[u];i!=-1;i=edge[i].next)
 50     {
 51         int v=edge[i].v;
 52         if (v==pre) continue;
 53         dfs1(v,u,depth+1);
 54         num[u]+=num[v];
 55         if (son[u]==-1 || num[v]>num[son[u]]) son[u]=v;
 56     }
 57 }
 58 
 59 void dfs2(int u,int sp)
 60 {
 61     top[u]=sp;
 62     p[u]=pos++;
 63     fp[p[u]]=u;
 64     if (son[u]==-1) return;
 65     dfs2(son[u],sp);
 66     for (int i=head[u];i!=-1;i=edge[i].next)
 67     {
 68         int v=edge[i].v;
 69         if (v!=fa[u] && v!=son[u]) dfs2(v,v);
 70     }
 71 }
 72 
 73 int lowbit(int x)
 74 {
 75     return x&(-x);
 76 }
 77 
 78 int c[MAXN];
 79 int n;
 80 int sum(int x)
 81 {
 82     int s=0;
 83     while (x>0)
 84     {
 85         s+=c[x];
 86         x-=lowbit(x);
 87     }
 88     return s;
 89 }
 90 
 91 void add(int x, int val)
 92 {
 93     while (x<=n)
 94     {
 95         c[x]+=val;
 96         x+=lowbit(x);
 97     }
 98 }
 99 
100 void update(int u,int v,int val)
101 {
102     int f1=top[u],f2=top[v];
103     int tmp=0;
104     while (f1!=f2)
105     {
106         if (deep[f1]<deep[f2])
107         {
108             swap(f1,f2);
109             swap(u,v);
110         }
111         // p[f1] <= p[u]
112         add(p[f1],val);
113         add(p[u]+1, -val);
114         u=fa[f1];
115         f1=top[u];
116     }
117     if (deep[u]>deep[v]) swap(u,v);
118     add(p[u],val);
119     add(p[v]+1,-val);
120 }
121 
122 int a[MAXN];
123 
124 int main()
125 {
126 #ifndef ONLINE_JUDGE
127     freopen("test.txt","r",stdin);
128 #endif // ONLINE_JUDGE
129     int M,P;
130     int u,v;
131     int C1,C2,val;
132     char op[10];
133     while (scanf("%d%d%d",&n,&M,&P)!=-1)
134     {
135         init();
136         for (int i=1;i<=n;++i) scanf("%d",&a[i]);
137         for (int i=1;i<=M;++i)
138         {
139             scanf("%d%d",&u,&v);
140             addEdge(u,v);
141             addEdge(v,u);
142         }
143         dfs1(1,0,0);
144         dfs2(1,1);
145         memset(c,0,sizeof(c));
146         for (int i=1;i<=n;++i)
147         {
148             add(p[i],a[i]);
149             add(p[i]+1,-a[i]);
150         }
151         for (int i=1;i<=P;++i)
152         {
153             scanf("%s",op);
154             if (op[0]==Q)
155             {
156                 scanf("%d",&u);
157                 printf("%d
",sum(p[u]));
158             }
159             else
160             {
161                 scanf("%d%d%d",&u,&v,&val);
162                 if (op[0]==D) val=-val;
163                 update(u,v,val);
164             }
165         }
166     }
167     return 0;
168 }

 

以上是关于树链剖分-基于点权的主要内容,如果未能解决你的问题,请参考以下文章

树链剖分详解

hdu3966 树链剖分+线段树 裸题

BZOJ 3626 LCA(离线+树链剖分)

D. Happy Tree Party CodeForces 593D树链剖分,树边权转点权

树链剖分模板

HDU 3966 Aragorn's Story(模板题)树链剖分+线段树