码迷,mamicode.com
首页 > 其他好文 > 详细

树链剖分膜版

时间:2017-05-26 20:39:28      阅读:197      评论:0      收藏:0      [点我收藏+]

标签:在线   make   rom   init   int   节点   getch   初步   ret   

十分weak的树链剖分初步

给一棵树,实现两个功能:

①给两个节点u,v,给u,v路上的每条边权值加a

②给两个节点u,v,求u,v路上所有边的权值之和

ps:在线操作

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<vector>
  5 using namespace std;
  6 
  7 inline int read(){
  8     char ch;
  9     int re=0;
 10     bool flag=0;
 11     while((ch=getchar())!=-&&(ch<0||ch>9));
 12     ch==-?flag=1:re=ch-0;
 13     while((ch=getchar())>=0&&ch<=9)  re=(re<<1)+(re<<3)+ch-0;
 14     return flag?-re:re;
 15 }
 16 
 17 struct edge{
 18     int to,next;
 19     edge(int to=0,int next=0):
 20         to(to),next(next){}
 21 };
 22 
 23 const int maxn=100001;
 24 
 25 vector<edge> edges;
 26 vector<edge> tree;
 27 int head[maxn],tmp_head[maxn];
 28 int n,q,root,cnt;
 29 int fat[maxn],dep[maxn],siz[maxn],son[maxn],top[maxn],id[maxn];
 30 //B[i]表示区间1...i变化量 
 31 int B[101];
 32 //C[i]表示区间1...i变化量的总和,有c[i]=b[i]*i 
 33 int C[101];
 34 
 35 inline void add_edge(int from,int to){
 36     edges.push_back(edge(to,head[from]));
 37     head[from]=++cnt;
 38     edges.push_back(edge(from,head[to]));
 39     head[to]=++cnt;
 40 }
 41 
 42 inline void add_tree(int from,int to){
 43     tree.push_back(edge(to,tmp_head[from]));
 44     tmp_head[from]=++cnt;
 45 }
 46 
 47 void init(){
 48     n=read();  q=read();  root=read();
 49     edges.push_back(edge(0,0));
 50     cnt=0;
 51     for(int i=1;i<n;i++){
 52         int from=read(),to=read();
 53         add_edge(from,to);
 54     }
 55 }
 56 
 57 void dfs_1(int x,int fa){
 58     fat[x]=fa;
 59     dep[x]=dep[fa]+1;
 60     siz[x]=1;
 61     int maxx=0;
 62     for(int ee=head[x];ee;ee=edges[ee].next)
 63         if(edges[ee].to!=fa){
 64             add_tree(x,edges[ee].to);
 65             dfs_1(edges[ee].to,x);
 66             if(siz[edges[ee].to]>maxx){
 67                 maxx=siz[edges[ee].to];
 68                 son[x]=edges[ee].to;
 69             }
 70             siz[x]+=siz[edges[ee].to];
 71         }
 72 }
 73 
 74 void dfs_2(int x){
 75     if(son[x]){
 76         top[son[x]]=top[x];
 77         id[son[x]]=++cnt;
 78         dfs_2(son[x]);
 79     }
 80     for(int ee=head[x];ee;ee=tree[ee].next)
 81         if(tree[ee].to!=son[x]){
 82             top[tree[ee].to]=tree[ee].to;
 83             id[tree[ee].to]=++cnt;
 84             dfs_2(tree[ee].to);
 85         }
 86 }
 87 
 88 void make(){
 89     cnt=0;
 90     dep[0]=0;
 91     tree.push_back(edge(0,0));
 92     dfs_1(root,0);
 93     swap(head,tmp_head);
 94     top[root]=root;
 95     cnt=0;
 96     dfs_2(root);
 97 }
 98 
 99 void ADD_B(int x, int c)
100 {
101      for (int i=x; i>0; i-=i&(-i)) B[i] += c;
102 }
103 
104 void ADD_C(int x, int c)
105 {
106      for (int i=x; i<=n; i+=i&(-i)) C[i] += x * c;
107 }
108 
109 int add(int left,int right,int c){
110     ADD_B(right,c);  ADD_C(right,c);
111     if(left-1){
112         ADD_B(left-1,-c);
113         ADD_C(left-1,-c);
114     }
115 }
116 
117 int SUM_B(int x)
118 {
119     int s = 0;
120     for(int i=x;i<=n;i+=i&(-i)) s+=B[i];
121     return s;
122 }
123 
124 int SUM_C(int x)
125 {
126     int s=0;
127     for (int i=x;i;i-=i&(-i)) s+=C[i];
128     return s;
129 }
130 
131 int SUM(int x)
132 {
133     if (x) return SUM_B(x)*x+SUM_C(x-1);
134     else return 0;
135 }
136 
137 int sum(int left,int right){
138     return SUM(right)-SUM(left-1);
139 }
140 
141 void cha(int u,int v,int a){
142     int f1=top[u],f2=top[v];
143     while(f1!=f2){
144         if(dep[f1]<dep[f2]){
145             swap(f1,f2);
146             swap(u,v);
147         }
148         add(id[f1],id[u],a);
149         u=fat[f1];  f1=top[u];
150     }
151     if(u==v)  return;
152     if(dep[u]<dep[v])  swap(u,v);
153     add(id[son[v]],id[u],a);
154 }
155 
156 int calc(int u,int v){
157     int f1=top[u],f2=top[v];
158     int len=0;
159     while(f1!=f2){
160         if(dep[f1]<dep[f2]){
161             swap(f1,f2);
162             swap(u,v);
163         }
164         len+=sum(id[f1],id[u]);
165         u=fat[f1];  f1=top[u];
166     }
167     if(u==v)  return len;
168     if(dep[u]<dep[v])  swap(u,v);
169     len+=sum(id[son[v]],id[u]);
170     return len;
171 }
172 
173 void solve(){
174     for(int i=0;i<q;i++){
175         int op=read(),ss=read(),tt=read();
176         if(op){
177             int a=read();
178             cha(ss,tt,a);
179         }
180         else{
181             printf("%d\n",calc(ss,tt));
182         }
183     }
184 }
185 
186 int main(){
187     //freopen("temp.in","r",stdin);
188     init();
189     make();
190     solve();
191     return 0;
192 }

她会好吗 还是更烂

对我而言 是另一天

树链剖分膜版

标签:在线   make   rom   init   int   节点   getch   初步   ret   

原文地址:http://www.cnblogs.com/ZYBGMZL/p/6910249.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!