ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

树链剖分

2019-10-30 12:04:12  阅读:227  来源: 互联网

标签:剖分 fa int res mid 树链 bl MAXN


我终于码了树链剖分,别人半年前学会的东西我终于入门辣!!!

先放全代码:


 

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<cmath>
  5 #define MAXN 30010
  6 using namespace std;
  7 const int INF=(1<<30);
  8 struct rr{
  9     int nt,to;
 10 }bl[MAXN<<1];int hd[MAXN],itot;
 11 void addedge(int x,int y){
 12     bl[++itot]=(rr){hd[x],y};
 13     hd[x]=itot;
 14     return ;
 15 }
 16 int n;
 17 int w[MAXN];
 18 int son[MAXN],L[MAXN],top[MAXN],sz[MAXN];
 19 int fat[MAXN];
 20 int sd[MAXN];
 21 int num=0;
 22 int line[MAXN];//dfs序上的某一个位置具体是哪个节点
 23 void dfs1(int u,int fa){
 24     sz[u]=1;fat[u]=fa;
 25     for(int i=hd[u],y;i;i=bl[i].nt)
 26         if(bl[i].to!=fa){
 27             y=bl[i].to;
 28             dfs1(y,u);
 29             sz[u]+=sz[y];
 30             if(sz[son[u]]<sz[y])son[u]=y;
 31         }
 32     return ;
 33 }
 34 void dfs2(int u,int fa,int dep){
 35     sd[u]=dep;
 36     L[u]=++num;line[num]=u;
 37     top[u]=(son[fa]==u)?top[fa]:u;
 38     if(son[u])dfs2(son[u],u,dep+1);
 39     for(int i=hd[u],y;i;i=bl[i].nt)
 40         if(bl[i].to!=fa&&bl[i].to!=son[u])dfs2(bl[i].to,u,dep+1);
 41     return ;
 42 }
 43 struct SEGTREE{
 44     int mx[MAXN*4],sm[MAXN*4];
 45     #define ls (u<<1)
 46     #define rs (u<<1|1)
 47     void up(int u){
 48         mx[u]=max(mx[ls],mx[rs]);
 49         sm[u]=sm[ls]+sm[rs];
 50         return ;
 51     }
 52     void build(int u,int l,int r){
 53         if(l==r){sm[u]=mx[u]=w[line[l]];return ; }
 54         int mid=l+r>>1;
 55         build(ls,l,mid),build(rs,mid+1,r);
 56         up(u);
 57         return ;
 58     }
 59     void upd(int u,int l,int r,int pos,int val){
 60         if(l==r){mx[u]=sm[u]=val;return ; }
 61         int mid=l+r>>1;
 62         if(pos<=mid)upd(ls,l,mid,pos,val);
 63         else upd(rs,mid+1,r,pos,val);
 64         up(u);
 65         return ;
 66     }
 67     int qwsm(int u,int l,int r,int x,int y){
 68         if(l>=x&&r<=y)return sm[u];
 69         int mid=l+r>>1;
 70         int res=0;
 71         if(mid>=x)res+=qwsm(ls,l,mid,x,y);
 72         if(mid+1<=y)res+=qwsm(rs,mid+1,r,x,y);
 73         return res;
 74     }
 75     int qwmx(int u,int l,int r,int x,int y){
 76         if(l>=x&&r<=y)return mx[u];
 77         int mid=l+r>>1;
 78         int res=-INF;
 79         if(mid>=x)res=max(res,qwmx(ls,l,mid,x,y));
 80         if(mid+1<=y)res=max(res,qwmx(rs,mid+1,r,x,y));
 81         return res;
 82     }
 83 }T;
 84 int q;
 85 int gtmx(int x,int y){
 86     int res=-INF;
 87     while(top[x]!=top[y]){
 88         if(sd[top[x]]<sd[top[y]])swap(x,y);
 89         res=max(res,T.qwmx(1,1,num,L[top[x]],L[x]));
 90         x=fat[top[x]];
 91     }
 92     if(sd[x]<sd[y])swap(x,y);
 93     res=max(res,T.qwmx(1,1,num,L[y],L[x]));
 94     return res;
 95 }
 96 int gtsm(int x,int y){
 97     int res=0;
 98     while(top[x]!=top[y]){
 99         if(sd[top[x]]<sd[top[y]])swap(x,y);
100         res+=T.qwsm(1,1,num,L[top[x]],L[x]);
101         x=fat[top[x]];
102     }
103     if(sd[x]<sd[y])swap(x,y);
104     res+=T.qwsm(1,1,num,L[y],L[x]);
105     return res;
106 }
107 int main(){
108     //freopen("count1.in","r",stdin);
109     //freopen("hh.out","w",stdout);
110     scanf("%d",&n);
111     for(int i=1,a,b;i<n;++i){
112         scanf("%d%d",&a,&b);
113         addedge(a,b);addedge(b,a);
114     }
115     for(int i=1;i<=n;++i)scanf("%d",&w[i]);
116     dfs1(1,0);dfs2(1,0,1);
117     T.build(1,1,num);
118     scanf("%d",&q);
119     char opt[17];
120     int u,v;
121     while(q--){
122         scanf("%s%d%d",opt,&u,&v);
123         if(opt[0]=='C')T.upd(1,1,num,L[u],v);
124         else if(opt[1]=='M')printf("%d\n",gtmx(u,v));
125         else printf("%d\n",gtsm(u,v));
126     }
127     return 0;
128 }
View Code

 

着重解释几个代码片:


 

需要维护的变量:

1 int son[MAXN];//重儿子
2 int L[MAXN];//dfs序中的位置
3 int top[MAXN];//所在重链的链顶
4 int sz[MAXN];//子树的大小
5 int fat[MAXN];
6 int sd[MAXN];//深度
7 int num=0;
8 int line[MAXN];//dfs序上的某一个位置具体是哪个节点

 

$dfs1$:

 1 void dfs1(int u,int fa){
 2     sz[u]=1;fat[u]=fa;
 3     for(int i=hd[u],y;i;i=bl[i].nt)
 4         if(bl[i].to!=fa){
 5             y=bl[i].to;
 6             dfs1(y,u);
 7             sz[u]+=sz[y];
 8             if(sz[son[u]]<sz[y])son[u]=y;//更新重儿子
 9         }
10     return ;
11 }

$dfs2$:

 1 void dfs2(int u,int fa,int dep){
 2     sd[u]=dep;
 3     L[u]=++num;line[num]=u;
 4     top[u]=(son[fa]==u)?top[fa]:u;
 5     //判断是否为链断
 6     if(son[u])dfs2(son[u],u,dep+1);
 7     //先dfs重儿子,确保一条重链的点在dfs序上是连续的
 8     for(int i=hd[u],y;i;i=bl[i].nt)
 9         if(bl[i].to!=fa&&bl[i].to!=son[u])dfs2(bl[i].to,u,dep+1);
10     return ;
11 }

建线段树就不说什么了

以询问两点路径最大值为例

$qwmx$:

 1 int gtmx(int x,int y){
 2     int res=-INF;
 3     while(top[x]!=top[y]){
 4         if(sd[top[x]]<sd[top[y]])swap(x,y);
 5         res=max(res,T.qwmx(1,1,num,L[top[x]],L[x]));
 6         x=fat[top[x]];
 7     }
 8     if(sd[x]<sd[y])swap(x,y);
 9     res=max(res,T.qwmx(1,1,num,L[y],L[x]));
10     return res;
11 }

 

例题:


 

先咕着,并没有做过几道题。。。

 

标签:剖分,fa,int,res,mid,树链,bl,MAXN
来源: https://www.cnblogs.com/2018hzoicyf/p/11764022.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有