ICode9

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

Luogu P3384 【模板】树链剖分

2019-04-19 21:47:39  阅读:283  来源: 互联网

标签:剖分 int Luogu sum tr P3384 tg dfn mod


。。。rt。。。安利一发大佬博客https://www.cnblogs.com/ivanovcraft/p/9019090.html

注意:不要把dfn和rw弄混了。。。

#include<cstdio>
#include<iostream>
#define ll long long
#define R register ll
#define ls (tr<<1)
#define rs (tr<<1|1)
const int M=100010;
using namespace std;
inline ll g() {
    R ret=0; register char ch; while(!isdigit(ch=getchar())) ; 
    do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret;
}
int n,m,tr,cnt,num,mod;
int vr[M<<1],nxt[M<<1],fir[M],dfn[M],pre[M],d[M],sz[M],son[M],top[M],rw[M],w[M];
int tg[M<<2],sum[M<<2];
inline void add(int u,int v) {vr[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt;}
void dfs(int u) { sz[u]=1; R mx=0;
    for(R i=fir[u];i;i=nxt[i]) { R v=vr[i];
        if(!d[v]) {
            pre[v]=u; d[v]=d[u]+1; dfs(v); sz[u]+=sz[v]; 
            if(sz[v]>mx) son[u]=v,mx=sz[v];
        }
    }
}
void dfs_(int u,int tp) {
    top[u]=tp,dfn[u]=++num,rw[num]=u;
    if(son[u]) dfs_(son[u],tp);
    for(R i=fir[u];i;i=nxt[i]) { R v=vr[i];
        if(v!=pre[u]&&v!=son[u]) dfs_(v,v);
    }
}
inline void build(int tr,int l,int r) {
    if(l==r) {sum[tr]=w[rw[l]]; if(sum[tr]>=mod) sum[tr]%=mod; return ;}
    R md=(l+r)>>1; build(ls,l,md),build(rs,md+1,r); 
    sum[tr]=(sum[ls]+sum[rs])%mod;
}
inline void spread(int tr,int len) {
    if(tg[tr]) 
        (tg[ls]+=tg[tr])%=mod,(sum[ls]+=(len-(len>>1))*tg[tr])%=mod,
        (tg[rs]+=tg[tr])%=mod,(sum[rs]+=(len>>1)*tg[tr])%=mod,tg[tr]=0;
}
inline int query(int tr,int l,int r,int LL,int RR) { R ret=0;
    if(LL<=l&&r<=RR) {return sum[tr];} spread(tr,r-l+1); R md=(l+r)>>1;
    if(LL<=md) (ret+=query(ls,l,md,LL,RR))%=mod;
    if(RR>md) (ret+=query(rs,md+1,r,LL,RR))%=mod; return ret;
}
inline void update(int tr,int l,int r,int LL,int RR,int inc) {
    if(LL<=l&&r<=RR) {(tg[tr]+=inc)%=mod,(sum[tr]+=(r-l+1)*inc)%=mod; return ;}
    spread(tr,r-l+1); R md=(l+r)>>1;
    if(LL<=md) update(ls,l,md,LL,RR,inc);
    if(RR>md) update(rs,md+1,r,LL,RR,inc);
    sum[tr]=(sum[ls]+sum[rs])%mod;
}
inline void change(int u,int v,int inc) {
    while(top[u]!=top[v]) {
        if(d[top[u]]<d[top[v]]) swap(u,v);
        update(1,1,n,dfn[top[u]],dfn[u],inc);
        u=pre[top[u]];
    } if(dfn[u]>dfn[v]) swap(u,v);
    update(1,1,n,dfn[u],dfn[v],inc);
}
inline int qTree(int u,int v) {
    R ret=0;
    while(top[u]!=top[v]) {
        if(d[top[u]]<d[top[v]]) swap(u,v);
        (ret+=query(1,1,n,dfn[top[u]],dfn[u]))%=mod;
        u=pre[top[u]];
    } if(dfn[u]>dfn[v]) swap(u,v); (ret+=query(1,1,n,dfn[u],dfn[v]))%=mod;
    return ret;
}
signed main() {
    n=g(),m=g(),tr=g(),mod=g();
    for(R i=1;i<=n;++i) w[i]=g();
    for(R i=1,u,v;i<n;++i) u=g(),v=g(),add(u,v),add(v,u); cnt=0;
    d[tr]=1; dfs(tr),dfs_(tr,tr); build(1,1,n);
    //for(R i=1;i<=n;++i) cout<<sz[i]<<d[i]<<dfn[i]<<pre[i]<<son[i]<<top[i]<<endl;
    for(R i=1;i<=m;++i) { 
        R k=g(),u=g(),v,inc; //cout<<k<<u<<endl;
        if(k==1) v=g(),inc=g(),change(u,v,inc%mod);
        else if(k==2) v=g(),printf("%lld\n",qTree(u,v));
        else if(k==3) v=g(),update(1,1,n,dfn[u],dfn[u]+sz[u]-1,v%mod);
        else printf("%lld\n",query(1,1,n,dfn[u],dfn[u]+sz[u]-1));
    }
}

2019.04.19

标签:剖分,int,Luogu,sum,tr,P3384,tg,dfn,mod
来源: https://www.cnblogs.com/Jackpei/p/10739020.html

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

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

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

ICode9版权所有