zoukankan      html  css  js  c++  java
  • 树链剖分

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

    先放全代码:


      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
    ",gtmx(u,v));
    125         else printf("%d
    ",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 }

    例题:


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

  • 相关阅读:
    MongoDB +JSON+JQuery.Pagination+Linq 实现无刷新分页
    DBHelper
    C# .Net动态调用webService
    .net 将图片文件转换成流输出到浏览器
    将mongodb作为服务
    .net 最简单文件上传支持跨服务器
    Windows Phone 7
    javascript中对Date类型的常用操作
    DataTable 转换JSON
    C# 实现 MemCache 监控管理工具
  • 原文地址:https://www.cnblogs.com/2018hzoicyf/p/11764022.html
Copyright © 2011-2022 走看看