[CodeVS4633][Mz]树链剖分练习

Posted skylee的OI博客

tags:

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

思路:

轻重链剖分+线段树。

  1 #include<cstdio>
  2 #include<vector>
  3 #include<cstring>
  4 const int N=100001;
  5 std::vector<int> e[N];
  6 inline void add_edge(const int u,const int v) {
  7     e[u].push_back(v);
  8     e[v].push_back(u);
  9 }
 10 int par[N]={0,1},dep[N]={0},size[N]={0};
 11 void dfs1(const int x) {
 12     size[x]=1;
 13     for(unsigned int i=0;i<e[x].size();i++) {
 14         if(e[x][i]==par[x]) continue;
 15         par[e[x][i]]=x,dep[e[x][i]]=dep[x]+1;
 16         dfs1(e[x][i]);
 17         size[x]+=size[e[x][i]];
 18     }
 19 }
 20 int top[N]={0},dfn[N],sz=0;
 21 void dfs2(const int x) {
 22     if(!top[x]) top[x]=x;
 23     dfn[x]=++sz;
 24     if(e[x].size()==1&&x!=1) return;
 25     int v=0;
 26     for(unsigned int i=0;i<e[x].size();i++) {
 27         if(e[x][i]==par[x]) continue;
 28         if(size[e[x][i]]>size[v]) v=e[x][i];
 29     }
 30     top[v]=top[x];
 31     dfs2(v);
 32     for(unsigned int i=0;i<e[x].size();i++) {
 33         if(e[x][i]==par[x]||e[x][i]==v) continue;
 34         dfs2(e[x][i]);
 35     }
 36 }
 37 class SegmentTree {
 38     #define _left <<1
 39     #define _right <<1|1
 40     private:
 41         int val[N<<2],tag[N<<2];
 42         int len(const int l,const int r) {
 43             return r-l+1;
 44         }
 45         void push_down(const int p,const int b,const int e) {
 46             if(!tag[p]) return;
 47             int mid=(b+e)>>1;
 48             tag[p _left]+=tag[p];
 49             tag[p _right]+=tag[p];
 50             val[p _left]+=tag[p]*len(b,mid);
 51             val[p _right]+=tag[p]*len(mid+1,e);
 52             tag[p]=0;
 53         }
 54         void push_up(const int p) {
 55             val[p]=val[p _left]+val[p _right];
 56         }
 57     public:
 58         SegmentTree() {
 59             memset(val,0,sizeof val);
 60             memset(tag,0,sizeof tag);
 61         }
 62         void modify(const int p,const int b,const int e,const int l,const int r) {
 63             if((b==l)&&(e==r)) {
 64                 val[p]+=len(b,e);
 65                 tag[p]++;
 66                 return;
 67             }
 68             push_down(p,b,e);
 69             int mid=(b+e)>>1;
 70             if(l<=mid) modify(p _left,b,mid,l,std::min(mid,r));
 71             if(r>mid) modify(p _right,mid+1,e,std::max(mid+1,l),r);
 72             push_up(p);
 73         }
 74         int query(const int p,const int b,const int e,const int l,const int r) {
 75             if((b==l)&&(e==r)) return val[p];
 76             push_down(p,b,e);
 77             int mid=(b+e)>>1,ans=0;
 78             if(l<=mid) ans+=query(p _left,b,mid,l,std::min(mid,r));
 79             if(r>mid) ans+=query(p _right,mid+1,e,std::max(mid+1,l),r);
 80             return ans;
 81         }
 82 };
 83 SegmentTree t;
 84 inline void swap(int &x,int &y) {
 85     int t;
 86     t=x;
 87     x=y;
 88     y=t;
 89 }
 90 int n;
 91 void modify(int x,int y) {
 92     for(;top[x]!=top[y];x=par[top[x]]) {
 93         if(dep[top[x]]<dep[top[y]]) swap(x,y);
 94         t.modify(1,1,n,dfn[top[x]],dfn[x]);
 95     }
 96     if(dep[x]<dep[y]) swap(x,y);
 97     t.modify(1,1,n,dfn[y],dfn[x]);
 98 }
 99 int query(int x,int y) {
100     int ans=0;
101     for(;top[x]!=top[y];x=par[top[x]]) {
102         if(dep[top[x]]<dep[top[y]]) swap(x,y);
103         ans+=t.query(1,1,n,dfn[top[x]],dfn[x]);
104     }
105     if(dep[x]<dep[y]) swap(x,y);
106     ans+=t.query(1,1,n,dfn[y],dfn[x]);
107     return ans;
108 }
109 int main() {
110     scanf("%d",&n);
111     for(int i=1;i<n;i++) {
112         int x,y;
113         scanf("%d%d",&x,&y);
114         add_edge(x,y);
115     }
116     dfs1(1);
117     dfs2(1);
118     int q;
119     scanf("%d",&q);
120     while(q--) {
121         int op,x,y;
122         scanf("%d%d%d",&op,&x,&y);
123         if(op==1) modify(x,y);
124         if(op==2) printf("%d\n",query(x,y));
125     }
126     return 0;
127 }

 

以上是关于[CodeVS4633][Mz]树链剖分练习的主要内容,如果未能解决你的问题,请参考以下文章

codevs 4633 [Mz]树链剖分练习

树链剖分(+线段树)(codevs4633)

codevs 1228 苹果树 树链剖分讲解

浅谈树链剖分

刷题总结——骑士的旅行(bzoj4336 树链剖分套权值线段树)

BZOJ 2243--染色(树链剖分)