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

    推荐博客:

    https://www.cnblogs.com/ivanovcraft/p/9019090.html

    这讲的很好,主要是用来处理树上路径问题的高效算法

    首先明确概念:

    重儿子:父亲节点的所有儿子中子树结点数目最多(size最大)的结点;

    轻儿子:父亲节点中除了重儿子以外的儿子;

    重边:父亲结点和重儿子连成的边;

    轻边:父亲节点和轻儿子连成的边;

    重链:由多条重边连接而成的路径;

    轻链:由多条轻边连接而成的路径;

    名称 解释
    f[u] 保存结点u的父亲节点
    d[u] 保存结点u的深度值
    size[u] 保存以u为根的子树节点个数
    son[u] 保存重儿子
    rk[u] 保存当前dfs标号在树中所对应的节点
    top[u] 保存当前节点所在链的顶端节点
    id[u] 保存树中每个节点剖分以后的新编号(DFS的执行顺序)

    题目:洛谷 https://www.luogu.org/problem/P3384

    ac代码:

      1 #include<bits/stdc++.h>
      2 const ll MAX=100000+5;
      3 ll p;
      4 vector<ll>q[maxn];
      5 ll f[maxn];
      6 ll d[maxn];
      7 ll siz[maxn];
      8 ll son[maxn];
      9 
     10 ll top[maxn];
     11 ll id[maxn];
     12 ll rk[maxn];
     13 
     14 ll a[maxn];
     15 
     16 struct Tree
     17 {
     18     ll l,r,sum;
     19 } tree[maxn<<2];
     20 ll dfs(ll a,ll fa)
     21 {
     22     f[a]=fa;
     23     d[a]=d[fa]+1;
     24     siz[a]=1;
     25     for(ll i=0; i<q[a].size(); i++)
     26     {
     27         ll z=q[a][i];
     28         if(z!=fa)
     29         {
     30             dfs(z,a);
     31             siz[a]+=siz[z];
     32             if(!son[a]||siz[z]>siz[son[a]])
     33                 son[a]=z;
     34         }
     35     }
     36     return 0;
     37 }
     38 ll lz[maxn];
     39 void build(ll x,ll l,ll r)
     40 {
     41     tree[x].l=l;
     42     tree[x].r=r;
     43     if(l==r)
     44         tree[x].sum=a[rk[l]];
     45     if(l==r)return ;
     46     ll mid=(l+r)>>1;
     47     build(x<<1,l,mid);
     48     build(x<<1|1,mid+1,r);
     49     tree[x].sum=(tree[x<<1].sum+tree[x<<1|1].sum);
     50 }
     51 void pushup(ll x)
     52 {
     53     ll LL,rr;
     54     LL=tree[x].l;
     55     rr=tree[x].r;
     56     ll k=lz[x];
     57     lz[x<<1]+=k;
     58     lz[x<<1|1]+=k;
     59     ll mid=(LL+rr)>>1;
     60     tree[x<<1].sum+=(mid-LL+1)*lz[x];
     61     tree[x<<1].sum%=p;
     62     tree[x<<1|1].sum+=(rr-mid)*lz[x];
     63     tree[x<<1|1].sum%=p;
     64     lz[x]=0;
     65 
     66 }
     67 
     68 void add(ll x,ll l,ll r,ll k)
     69 {
     70     ll LL,rr;
     71     LL=tree[x].l;
     72     rr=tree[x].r;
     73     if(l<=LL&&rr<=r)
     74     {
     75         tree[x].sum=(tree[x].sum+(rr-LL+1)*k)%p;
     76         lz[x]+=k;
     77         return ;
     78     }
     79     if(lz[x]) pushup(x);
     80     ll mid=(LL+rr)>>1;
     81     if(mid>=l) add(x<<1,l,r,k);
     82     if(mid<r)add(x<<1|1,l,r,k);
     83     tree[x].sum=(tree[x<<1].sum+tree[x<<1|1].sum)%p;
     84 }
     85 ll pri(ll x,ll l,ll r)
     86 {
     87     ll sum=0;
     88     ll LL,rr;
     89     LL=tree[x].l;
     90     rr=tree[x].r;
     91     if(l<=LL&&rr<=r)
     92     {
     93         return tree[x].sum;
     94     }
     95     if(lz[x]) pushup(x);
     96     ll mid=(LL+rr)>>1;
     97     if(mid>=l) sum+=pri(x<<1,l,r);
     98     sum%=p;
     99     if(mid<r)sum+=pri(x<<1|1,l,r);
    100     return sum%p;
    101 }
    102 ll sum;
    103 void dfs1(ll a,ll b)
    104 {
    105     top[a]=b;
    106     id[a]=++sum;
    107     rk[sum]=a;
    108     if(!son[a])
    109         return ;
    110     dfs1(son[a],b);
    111     for(ll i=0; i<q[a].size(); i++)
    112     {
    113         ll z=q[a][i];
    114         if(z!=f[a]&&z!=son[a])
    115             dfs1(z,z);
    116     }
    117 }
    118 void Q1(ll x,ll y,ll z)
    119 {
    120     while(top[x]!=top[y])
    121     {
    122         if(d[top[x]]<d[top[y]])swap(x,y);
    123         add(1,id[top[x]],id[x],z);
    124         x=f[top[x]];
    125     }
    126     if(d[x]>d[y])swap(x,y);
    127     add(1,id[x],id[y],z);
    128 }
    129 ll Q2(ll x,ll y)
    130 {
    131     ll sum=0;
    132     while(top[x]!=top[y])
    133     {
    134         if(d[top[x]]<d[top[y]])swap(x,y);
    135         sum=(sum+pri(1,id[top[x]],id[x]))%p;
    136         x=f[top[x]];
    137     }
    138     if(d[x]>d[y])swap(x,y);
    139     sum=(sum+pri(1,id[x],id[y]))%p;
    140     return (sum+p)%p;
    141 }
    142 void Q3(ll x,ll z)
    143 {
    144     add(1,id[x],id[x]+siz[x]-1,z);
    145 }
    146 int main()
    147 {
    148     // ios::sync_with_stdio(false);
    149     ll  n,m,r;
    150     scanf("%lld%lld%lld%lld",&n,&m,&r,&p);
    151     for(ll i=1; i<=n; i++)
    152         scanf("%lld",&a[i]);
    153     for(ll i=1; i<n; i++)
    154     {
    155         ll x,y;
    156         scanf("%lld%lld",&x,&y);
    157         q[x].pb(y);
    158         q[y].pb(x);
    159     }
    160     dfs(r,0);
    161     dfs1(r,r);
    162     build(1,1,n);
    163     while(m--)
    164     {
    165         ll a;
    166         cin>>a;
    167         if(a==1)
    168         {
    169             ll x,y,z;
    170             scanf("%lld%lld%lld",&x,&y,&z);z%=p;
    171             Q1(x,y,z);
    172         }
    173         else if(a==2)
    174         {
    175             ll x,y;
    176             cin>>x>>y;
    177             cout<<Q2(x,y)<<endl;
    178         }
    179         else if(a==3)
    180         {
    181             ll x,z;z%=p;
    182             cin>>x>>z;
    183             Q3(x,z);
    184         }
    185         else
    186         {
    187             ll x;
    188             cin>>x;
    189             cout<<(pri(1,id[x],id[x]+siz[x]-1)+p)%p<<endl;
    190         }
    191     }
    192 }
    View Code
  • 相关阅读:
    /etc/fstab 文件解释
    CRLF和LF
    Git远程操作详解
    jsp错误处理
    jsp隐式对象
    关于循环队列要注意的
    JSP动作元素
    JSP指令
    jsp语法简介
    jsp声明周期
  • 原文地址:https://www.cnblogs.com/zxz666/p/11272911.html
Copyright © 2011-2022 走看看