ICode9

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

树链剖分

2019-05-24 20:53:57  阅读:224  来源: 互联网

标签:剖分 fx fy top long 树链 mod rk


https://www.luogu.org/problemnew/show/P3384

知识点 :1.先切割重边,还记得求出top

     2.线段树维护dfs序下的val数组,一条链上的数在dfs序中是连续的

    3.求值时就在树上跑,优化在于一条链上的信息可以直接求,顾跳top即可

There is a false in the code : False 1 

 

#include <bits/stdc++.h>
#define M 200002
using namespace std;
long long n,m,rt,mod;
long long tot = 0;
long long val[M];
long long head[M * 4],cnt = 0;
struct edge
{
    long long to;
    long long nxt;
}e[M * 4];
void add(long long x,long long y)
{
    e[++cnt].nxt = head[x];
    e[cnt].to = y;
    head[x] = cnt;
} 
long long siz[M];
long long son[M],rk[M],tp[M],fa[M],dep[M],top[M];
long long tre[M * 4],lazy[M * 4];
void build(long long t,long long l,long long r)
{
    if(l == r)
    {
        tre[t] = tp[l];
        return;
    }
    long long mid = (l + r) / 2;
    build(t *  2,l,mid);
    build(t * 2 + 1,mid + 1,r);
    tre[t] = (tre[t * 2] + tre[t * 2 + 1]) %  mod; 
}
void up(long long t,long long l,long long r,long long x)
{
    lazy[t] += x;
    lazy[t] %= mod;
    tre[t] += (r - l + 1) * x;
    tre[t] %= mod;
}
void pushdown(long long l,long long r,long long t)
{
    long long mid = (l + r) / 2;
    up(t * 2,l,mid,lazy[t]);
    up(t * 2 + 1,mid + 1,r,lazy[t]);
    lazy[t] = 0;
}
long long query(long long t,long long l,long long r,long long b,long long e)
{
    if(b <= l && r <= e)
    {
        return tre[t] % mod;
    }
    long long mid = (l + r) / 2;
    pushdown(l,r,t);
    long long ans = 0;
    if(b <= mid)ans += query(t * 2,l,mid,b,e);
    ans = ans % mod;
    if(mid < e)ans += query(t * 2 + 1,mid + 1,r,b,e);
    return ans % mod;
}
void updata(long long t,long long l,long long r,long long b,long long e,long long k)
{
    if(b <= l && r <= e)
    {
        tre[t] += (r - l + 1) * k;
        tre[t] %= mod;
        lazy[t] += k;
        lazy[t] %= mod;
        return;
    }
    long long mid = (l + r) / 2;
    pushdown(l,r,t);
    if(b <= mid)updata(t * 2,l,mid,b,e,k);
    if(mid < e)updata(t * 2 + 1,mid + 1,r,b,e,k);
    tre[t] = (tre[t * 2] + tre[t * 2 + 1]) % mod;
}
void dfs1(long long x,long long depth,long long fat)
{
    fa[x] = fat;
    dep[x] = depth;
    siz[x] = 1;
    long long maxn = -1;
    for(long long i = head[x];i;i = e[i].nxt)
    {
        if(e[i].to != fat)
        {
            dfs1(e[i].to,depth + 1,x);
            siz[x] += siz[e[i].to];
            if(maxn < siz[e[i].to] || maxn == -1)
            {
                son[x] = e[i].to;
                maxn = siz[e[i].to];
            }
        }
    }
}
void qupdata(long long l,long long r,long long k)
{
    k %= mod;
    long long fx = l,fy = r;    
    while(top[fx] != top[fy])
    {
        if(dep[top[fx]] < dep[top[fy]])swap(fx,fy);//False 1 : 这里应该是dep[top[fx]] < dep[top[fy]]而并非dep[fx] < dep[fy] 
        updata(1,1,n,rk[top[fx]],rk[fx],k);
        fx = fa[top[fx]];
    }
    if(dep[fx] > dep[fy])swap(fx,fy);
    updata(1,1,n,rk[fx],rk[fy],k);
} 
long long qquery(long long l,long long r)
{
    long long ans = 0;
    long long fx = l ,fy = r;
    while(top[fx] != top[fy])
    {
        if(dep[top[fx]] < dep[top[fy]])swap(fx,fy);
        ans += query(1,1,n,rk[top[fx]],rk[fx]);
        ans %= mod;
        fx = fa[top[fx]];
    }
    if(dep[fx] > dep[fy])swap(fx,fy);
    ans += query(1,1,n,rk[fx],rk[fy]);
    ans %= mod;
    return ans;
}
void rupdata(long long x,long long k)
{
    k %= mod;
    updata(1,1,n,rk[x],rk[x] + siz[x] - 1,k);
}
long long rquery(long long x)
{
    return query(1,1,n,rk[x],rk[x] + siz[x] - 1) % mod;
}
void dfs2(long long x,long long t)
{
    rk[x] = ++tot;
    tp[tot] = val[x];
    top[x] = t;
    if(!son[x])return;
    dfs2(son[x],t);
    for(long long i = head[x];i;i = e[i].nxt)
    {
        long long y = e[i].to;
        if(y != son[x] && y != fa[x])
            dfs2(y,y);
    }
}
int main()
{
    scanf("%lld%lld%lld%lld",&n,&m,&rt,&mod);
    for(long long i = 1;i <= n;i++)scanf("%lld",&val[i]);
    long long x,y,z,a;
    for(long long i = 1;i < n;i++)
    {
        scanf("%lld%lld",&x,&y);
        add(x,y);
        add(y,x);
    }
    dfs1(rt,1,0);
    dfs2(rt,rt);
    build(1,1,n);
    while(m--)
    {
        scanf("%lld",&a);
        if(a == 1)
        {
            scanf("%lld%lld%lld",&x,&y,&z);
            qupdata(x,y,z);    
        }
        else if(a == 2)
        {
            scanf("%lld%lld",&x,&y);
            printf("%lld\n",qquery(x,y) % mod);            
        }
        else if(a == 3)
        {
            scanf("%lld%lld",&x,&y);
            rupdata(x,y);    
        }
        else if(a == 4)
        {
            scanf("%lld",&x);
            printf("%lld\n",rquery(x) % mod);
        }
    }
    return 0;
}

 

标签:剖分,fx,fy,top,long,树链,mod,rk
来源: https://www.cnblogs.com/xyj1/p/10920108.html

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

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

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

ICode9版权所有