树链剖分板子30pts求调

P3384 【模板】重链剖分/树链剖分

ben090302 @ 2023-01-07 13:24:04

数据点1 3 4过了,其他的提示在xx行无输出,是树状数组写法,调了半天没调出来,求救

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=100010;
struct gr{//链式前向星存图 
    int to,nxt;
}g[maxn*2]; 
int tot,head[maxn],c[maxn],t[maxn];
int fa[maxn],dep[maxn],son[maxn],siz[maxn],top[maxn],dfn[maxn],w[maxn],tim,v[maxn];

void adeg(int u,int v){
    g[++tot].to=v;
    g[tot].nxt=head[u];
    head[u]=tot;
}

int n,m,r,p;

int lb(int x){
    return x&(-x);
}

void build(){
    for(int i=1;i<=n;i++){
       int prt=w[i]-w[i-1];
       c[i]+=prt,t[i]+=prt*(i-1);
       if(i+lb(i)<=n) c[i+lb(i)]+=c[i],t[i+lb(i)]+=t[i];
    }
}

void add(int x,int k){
    for(int i=x;i<=n;i+=lb(i))c[i]+=k,t[i]+=k*(x-1);
}

int query(int x){
    int ret=0;
    for(int i=x;i;i-=lb(i)) ret+=x*c[i]-t[i],ret%=p;
    return (ret+p)%p;
}

void dfs1(int u,int f){//u=当前节点,f=u的跌 
    fa[u]=f;
    dep[u]=dep[f]+1;
    siz[u]=1;
    int msize=-1;
    for(int i=head[u];i;i=g[i].nxt){
        int v=g[i].to;
        if(v==f) continue;
        dfs1(v,u);
        siz[u]+=siz[v];
        if(siz[v]>msize){
            msize=siz[v];
            son[u]=v;
        }
    }
}

void dfs2(int u,int tp){//u为当前节点,t为当前链的顶端 
    dfn[u]=++tim;
    top[u]=tp;
    w[tim]=v[u];
    if(!son[u]) return;
    dfs2(son[u],tp);
    for(int i=head[u];i;i=g[i].nxt){
        int v=g[i].to;
        if(v==fa[u] or v==son[u]) continue;
        dfs2(v,v);
    }
}

void mson(int x,int z){//修改子树 操作3 
    add(dfn[x],z);
    add(dfn[x]+siz[x],-z);
}

int qson(int x){//查询子树 操作4 
    return (query(dfn[x]+siz[x]-1)-query(dfn[x]-1)+p)%p;
}

void mline(int x,int y,int z){//修改x到y最短路径 操作1 
    z%=p;
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        add(dfn[top[x]],z),add(dfn[x]+1,-z);
        x=fa[top[x]];
    }
    if(dep[x]>dep[y]) swap(x,y);
    add(dfn[x],z),add(dfn[y]+1,-z);
}

int qline(int x,int y){//查询x到y最短路径 操作2 
    int ret=0;
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        ret+=query(dfn[x])-query(dfn[top[x]]-1);
        ret%=p;
        x=fa[top[x]];
    }
    if(dep[x]>dep[y]) swap(x,y);
    ret+=query(dfn[y])-query(dfn[x]-1);
    return (ret+p)%p;
}

signed main(){
    cin>>n>>m>>r>>p;
    for(int i=1;i<=n;i++) cin>>v[i];
    for(int i=1;i<n;i++){
        int u,v;
        cin>>u>>v;
        adeg(u,v),adeg(v,u);
    }
    dfs1(r,r),dfs2(r,r);
    build();//树状数组预处理 
    while(m--){
        int mt,x,y,z;
        cin>>mt;
        if(mt==1) cin>>x>>y>>z,mline(x,y,z);
        else if(mt==2) cin>>x>>y,cout<<qline(x,y)<<"\n";
        else if(mt==3) cin>>x>>z,mson(x,z);
        else cin>>x,cout<<qson(x)<<"\n";
    }
}

by ben090302 @ 2023-01-08 08:06:52

取模出锅,此贴结


|