首页 > 其他 > 详细

树链剖分学习笔记

时间:2018-07-20 16:23:18      阅读:157      评论:0      收藏:0      [点我收藏+]

 毕竟刚学到了皮毛,还不足以讲,所以我只写一下我的见解,如果想较为深入的学习的话,请观摩博客:https://www.cnblogs.com/zwfymqz/p/8094500.html3

下面代码是这道题目的AC代码:luogu P3384 【模板】树链剖分

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 using namespace std;
  5 const int N = 100001;
  6 int deep[N],fa[N],son[N],size[N],idx[N],cnt,top[N],n,m,r,p,tot,head[N],a[N],b[N];
  7 struct edge
  8 {
  9     int next,to;
 10 } e[N<<1];
 11 struct T
 12 {
 13     int l,r,w,f;
 14 } tree[N<<2];
 15 inline void add(int x,int y)
 16 {
 17     e[++tot].next=head[x];
 18     e[tot].to=y;
 19     head[x]=tot;
 20 }
 21 void comup(int k)
 22 {
 23     tree[k].w=tree[k<<1].w+tree[k<<1|1].w;
 24 }
 25 void dfs1(int x,int f)
 26 {
 27     fa[x]=f;
 28     size[x]=1;
 29     for(int i=head[x]; i!=-1; i=e[i].next)
 30     {
 31         if(!deep[e[i].to] && e[i].to != f)
 32         {
 33             deep[e[i].to]=deep[x]+1;
 34             dfs1(e[i].to,x);
 35             size[x]+=size[e[i].to];
 36             if(size[e[i].to]>size[son[x]]) son[x]=e[i].to;
 37         }
 38     }
 39 }
 40 void dfs2(int x,int topf)
 41 {
 42     idx[x] = ++cnt;
 43     top[x] = topf;
 44     if(!son[x]) return;
 45     dfs2(son[x],topf);
 46     for(int i=head[x]; i!=-1; i=e[i].next)
 47         if(!top[e[i].to]) dfs2(e[i].to,e[i].to);
 48 }
 49 void build(int k,int ll,int rr)
 50 {
 51     tree[k].l=ll,tree[k].r=rr;
 52     if(ll==rr)
 53     {
 54         tree[k].w=a[ll];
 55         return;
 56     }
 57     int m=(ll+rr)>>1;
 58     build(k<<1,ll,m);
 59     build(k<<1|1,m+1,rr);
 60     comup(k);
 61 }
 62 void down(int k)
 63 {
 64     if(tree[k].f)
 65     {
 66         tree[k<<1].f=(tree[k<<1].f+tree[k].f)%p;
 67         tree[k<<1|1].f=(tree[k<<1|1].f+tree[k].f)%p;
 68         tree[k<<1].w=(tree[k<<1].w+(tree[k<<1].r-tree[k<<1].l+1)*tree[k].f)%p;
 69         tree[k<<1|1].w=(tree[k<<1|1].w+(tree[k<<1|1].r-tree[k<<1|1].l+1)*tree[k].f)%p;
 70         tree[k].f=0;
 71     }
 72 }
 73 void add_interval(int k,int ll,int rr,int y)
 74 {
 75     if(tree[k].l>=ll&&tree[k].r<=rr)
 76     {
 77         tree[k].w=(tree[k].w+(tree[k].r-tree[k].l+1)*y)%p;
 78         tree[k].f=(tree[k].f+y)%p;
 79         return;
 80     }
 81     down(k);
 82     int m=(tree[k].l+tree[k].r)>>1;
 83     if(ll<=m) add_interval(k<<1,ll,rr,y);
 84     if(rr>m) add_interval(k<<1|1,ll,rr,y);
 85     comup(k);
 86 }
 87 int asksum_interval(int k,int ll,int rr)
 88 {
 89     int ans=0;
 90     if(tree[k].l>=ll&&tree[k].r<=rr)
 91     {
 92         ans=(ans+tree[k].w)%p;
 93         return ans;
 94     }
 95     down(k);
 96     int m=(tree[k].l+tree[k].r)>>1;
 97     if(ll<=m) ans=(ans+asksum_interval(k<<1,ll,rr))%p;
 98     if(rr>m) ans=(ans+asksum_interval(k<<1|1,ll,rr))%p;
 99     comup(k);
100     return ans;
101 }
102 int asksum_tree(int x,int y)
103 {
104     int ans=0;
105     while(top[x]!=top[y])
106     {
107         if(deep[top[x]]<deep[top[y]]) swap(x,y);
108         ans=(ans+asksum_interval(1,idx[top[x]],idx[x]))%p;
109         x=fa[top[x]];
110     }
111     if(deep[x]<deep[y]) swap(x,y);
112     return (ans+asksum_interval(1,idx[y],idx[x]))%p;
113 }
114 void add_tree(int x,int y,int val)
115 {
116     while(top[x]!=top[y])
117     {
118         if(deep[top[x]]<deep[top[y]]) swap(x,y);
119         add_interval(1,idx[top[x]],idx[x],val);
120         x=fa[top[x]];
121     }
122     if(deep[x]<deep[y]) swap(x,y);
123     add_interval(1,idx[y],idx[x],val);
124 }
125 int main()
126 {
127     memset(head,-1,sizeof(head));
128     cin >> n >> m >> r >> p;
129     for(int i=1; i<=n; i++)cin>>b[i],b[i]=b[i]%p;
130     for(int i=1; i<=n-1; i++)
131     {
132         int a,b;
133         cin >> a >> b;
134         add(a,b);
135         add(b,a);
136     }
137     deep[r]=1;
138     dfs1(r,0);
139     dfs2(r,r);
140     for(int i=1; i<=n; i++)a[idx[i]] = b[i];
141     build(1,1,n);
142     for(int i=1; i<=m; i++)
143     {
144         int flag,x,y,c;
145         cin >> flag;
146         if(flag==1)
147         {
148             cin >> x >> y >> c;
149             add_tree(x,y,c);
150         }
151         if(flag==2)
152         {
153             cin >> x >> y;
154             cout<<asksum_tree(x,y)<<endl;
155         }
156         if(flag==3)
157         {
158             cin >> x >> c;
159             c=c%p;
160             add_interval(1,idx[x],idx[x]+size[x]-1,c);
161         }
162         if(flag==4)
163         {
164             cin >> x;
165             cout<<asksum_interval(1,idx[x],idx[x]+size[x]-1)<<endl;
166         }
167     }
168     return 0;
169 }

 

树链剖分学习笔记

原文:https://www.cnblogs.com/ifmyt/p/9342038.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!