数链剖分小结

就是把树上的路径拆成几段,然后大多按照线段树的解法解就可以了

讲解

http://blog.sina.com.cn/s/blog_7a1746820100wp67.html

模板

  1 #pragma comment(linker, "/STACK:1024000000,1024000000")
  2 #include <iostream>
  3 #include<cstdio>
  4 #include<cstring>
  5 #include<algorithm>
  6 #include<stdlib.h>
  7 #include<vector>
  8 #include<cmath>
  9 #include<queue>
 10 #include<set>
 11 using namespace std;
 12 #define N 50006
 13 #define INF 0xfffffff
 14 const double eps = 1e-8;
 15 const double pi = acos(-1.0);
 16 const double inf = ~0u>>2;
 17 /*
 18 fa[u]  u的父亲节点
 19 son[u] u的儿子节点
 20 dep[u] u的深度
 21 top[u] u所在链的深度最小的点
 22 siz[u] 以u为根的子树上的节点总数
 23 po[u] u在dfs时的时间戳
 24 */
 25 struct node
 26 {
 27     int u,v,next;
 28 } ed[N<<1];
 29 int head[N],t;
 30 int a[N];
 31 
 32 void add(int u,int v)
 33 {
 34     ed[t].u = u,ed[t].v = v;
 35     ed[t].next = head[u];
 36     head[u] = t++;
 37 }
 38 int siz[N],fa[N],son[N],dep[N],top[N],seg[N],po[N];
 39 int tp;
 40 void init()
 41 {
 42     t = 0;tp=0;
 43     memset(head,-1,sizeof(head));
 44     memset(son,-1,sizeof(son));
 45 }
 46 void dfs1(int u,int pre,int d)
 47 {
 48     dep[u] = d,fa[u] = pre,siz[u] = 1,son[u] = -1;
 49     for(int i = head[u] ; i!=-1 ; i = ed[i].next)
 50     {
 51         int v = ed[i].v;
 52         if(v!=pre)
 53         {
 54             dfs1(v,u,d+1);
 55             if(son[u]==-1||siz[son[u]]<siz[v])
 56                 son[u] = v;
 57             siz[u]+=siz[v];
 58         }
 59     }
 60 }
 61 
 62 void dfs2(int u,int pre,int tu)
 63 {
 64     top[u] = tu,po[u] = ++tp,seg[tp] = u;
 65     if(son[u]==-1) return ;
 66     dfs2(son[u],u,tu);
 67     for(int i = head[u]; i!=-1;  i =ed[i].next)
 68     {
 69         int v = ed[i].v;
 70         if(v!=fa[u]&&v!=son[u])
 71         dfs2(v,u,v);
 72     }
 73 }
 74 int s[N<<2];
 75 int n;
 76 void build(int l,int r,int w)
 77 {
 78     s[w] = 0;
 79     if(l==r)
 80     {
 81         s[w] = a[seg[l]];
 82         return ;
 83     }
 84     int m = (l+r)>>1;
 85     build(l,m,w<<1);
 86     build(m+1,r,w<<1|1);
 87 }
 88 void down(int w,int m)
 89 {
 90     if(s[w])
 91     {
 92         s[w<<1]+=s[w];
 93         s[w<<1|1]+=s[w];
 94         s[w] = 0;
 95     }
 96 }
 97 void update(int a,int b,int va,int l,int r,int w)
 98 {
 99     if(a<=l&&b>=r)
100     {
101         s[w]+=va;
102         return ;
103     }
104     down(w,r-l+1);
105     int m = (l+r)>>1;
106     if(a<=m) update(a,b,va,l,m,w<<1);
107     if(b>m) update(a,b,va,m+1,r,w<<1|1);
108 }
109 int query(int p,int l,int r,int w)
110 {
111     if(l==r)
112     {
113         return s[w];
114     }
115     down(w,r-l+1);
116     int m = (l+r)>>1;
117     if(p<=m) return query(p,l,m,w<<1);
118     else return  query(p,m+1,r,w<<1|1);
119 }
120 void solve(int l,int r,int val)
121 {
122     while(top[l]!=top[r])
123     {
124         if(dep[top[l]]<dep[top[r]]) swap(l,r);
125         update(po[top[l]],po[l],val,1,n,1);
126         l = fa[top[l]];
127     }
128     if(dep[l]>dep[r]) swap(l,r);
129     //对于结点值的操作
130     update(po[l],po[r],val,1,n,1);
131     /* 对于边权的话,需要减掉lca(l,r) 所以对seg[l]+1操作即可
132         if(l!=r)
133         update(po[l]+1,po[r],val,1,n,1);
134     */
135 }
136 int main()
137 {
138     int i,m,Q;
139     char str[20];
140     while(scanf("%d%d%d",&n,&m,&Q)!=EOF)
141     {
142         init();
143         for(i = 1; i <= n ;i++)
144         scanf("%d",&a[i]);
145         for(i = 1; i < n; i++)
146         {
147             int u,v;
148             scanf("%d%d",&u,&v);
149             add(u,v);
150             add(v,u);
151         }
152         dfs1(1,-1,1);
153 
154         dfs2(1,-1,1);
155         build(1,n,1);
156         while(Q--)
157         {
158             int x,y,z;
159             scanf("%s",str);
160 
161             if(str[0]=='I')
162             {
163                 scanf("%d%d%d",&x,&y,&z);
164                 solve(x,y,z);
165             }
166             else if(str[0]=='D')
167             {
168                 scanf("%d%d%d",&x,&y,&z);
169                 solve(x,y,-z);
170             }
171             else
172             {
173                 scanf("%d",&x);
174                 printf("%d\n",query(po[x],1,n,1));
175             }
176         }
177     }
178     return 0;
179 }
View Code

 

posted @ 2014-05-06 00:11  _雨  阅读(270)  评论(0编辑  收藏  举报