RE求调

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

xyztapeplayer @ 2024-04-26 17:18:37


#include<bits/stdc++.h>
using namespace std;
struct node{
    int l,r,sum,lz;
};
node tree[400005];
vector<int> a[400005];
int in[400005],deep[400005],siz[400005],fa[400005],son[400005],rnk[400005],top[400005],dfn[400005],cnt,n,m,mod,root;
void build(long long p,long long l,long long r){
    tree[p].l=l,tree[p].r=r;
    if(l==r){tree[p].sum=rnk[l];return;}
    long long mid=(l+r)/2;
    build(p*2,l,mid);
    build(p*2+1,mid+1,r);
    tree[p].sum=(tree[p*2].sum+tree[p*2+1].sum)%mod;
}

void push_down(int p){
    if(!tree[p].lz) return; 
    tree[p*2].lz+=tree[p].lz;
    tree[p*2+1].lz+=tree[p].lz;
    int mid=(tree[p].l+tree[p].r)/2;
    tree[p*2].sum+=tree[p].lz*(mid-tree[p*2].l+1);
    tree[p*2+1].sum+=tree[p].lz*(tree[p*2+1].r-mid);
    tree[p].lz=0;
}
void add(int p,int l,int r,int k){
//  cout<<p<<" "<<l<<" "<<r<<endl;
    if(tree[p].l>=l&&tree[p].r<=r){
        tree[p].sum+=k*(tree[p].r-tree[p].l+1);
        tree[p].lz+=k;
        return;
    }
    push_down(p);
    int mid=(tree[p].l+tree[p].r)/2;
    if(mid>=l) add(p*2,l,r,k);
    if(mid<r) add(p*2+1,l,r,k);
    tree[p].sum=(tree[p*2].sum+tree[p*2+1].sum)%mod;
    //cout<<tree[p].l<<" "<<tree[p].r<<" "<<tree[p].sum<<endl;
}
int search(int p,int l,int r){
    if(tree[p].l>=l&&tree[p].r<=r){
        return tree[p].sum;
    }
    if(tree[p].r<l||tree[p].l>r) return 0;
    push_down(p);
    int s=0;
    int mid=(tree[p].l+tree[p].r)/2;
    if(mid>=l) s+=search(p*2,l,r);
    s%=mod;
    if(mid<r) s+=search(p*2+1,l,r);
    s%=mod;
    //cout<<tree[p].l<<" "<<tree[p].r<<" "<<s<<endl;
    return s;
}
void dfs1(int u,int f){
    siz[u]=1;
//  cout<<u<<endl;
    for(int i=0;i<a[u].size();i++){
        if(a[u][i]==f) continue;
//      cout<<i<<":"<<a[u][i]<<endl;
        fa[a[u][i]]=u;
        deep[a[u][i]]=deep[u]+1;
        dfs1(a[u][i],u);
        siz[u]+=siz[a[u][i]];
        if(siz[a[u][i]]>siz[son[u]]) son[u]=a[u][i];
    }
}
void dfs2(int u,int tp){
    dfn[u]=++cnt;
    top[u]=tp;
    rnk[cnt]=in[u];
    if(!son[u]) return;
    dfs2(son[u],tp);
    for(int i=0;i<a[u].size();i++){
        if(a[u][i]!=fa[u]&&a[u][i]!=son[u]) 
            dfs2(a[u][i],a[u][i]);
    }
}
void addtree(int x,int y,int c){
    while(top[x]!=top[y]){
        if(deep[top[x]]<deep[top[y]]) swap(x,y);
        add(1,dfn[top[x]],dfn[x],c);
        x=fa[top[x]];
    }
    if(deep[x]>deep[y]) swap(x,y);
    add(1,dfn[x],dfn[y],c);
}
int searchtree(int x,int y){
    int ans=0;
    while(top[x]!=top[y]){
        if(deep[top[x]]<deep[top[y]]) swap(x,y);
        ans+=search(1,dfn[top[x]],dfn[x]);
        ans%=mod;
        x=fa[top[x]];
    }
    if(deep[x]>deep[y]) swap(x,y);
    ans+=search(1,dfn[x],dfn[y]);
    ans%=mod;
    return ans;
} 
int main(){
    cin>>n>>m>>root>>mod;
    for(int i=1;i<=n;i++) cin>>in[i];
    for(int i=1;i<n;i++){
        int u,v;
        cin>>u>>v;
        a[u].push_back(v);
        a[v].push_back(u);
    }
//  cout<<"图:"<<endl;
//  for(int i=1;i<=n;i++){
//      cout<<i<<": ";
//      for(int j=0;j<a[i].size();j++) cout<<a[i][j]<<" ";
//      cout<<endl;
//  }
//  cout<<"dfs1:"<<endl;
    fa[root]=root;
    dfs1(root,root);
    dfs2(root,root);
//  build(1,1,n);
//  cout<<"dfs序: ";
//  for(int i=1;i<=n;i++) cout<<dfn[i]<<" ";
//  cout<<endl<<"子树大小: ";
//  for(int i=1;i<=n;i++) cout<<siz[i]<<" ";
//  cout<<endl<<"重儿子: ";
//  for(int i=1;i<=n;i++) cout<<son[i]<<" ";
//  cout<<endl<<"深度: ";
//  for(int i=1;i<=n;i++) cout<<deep[i]<<" ";
//  cout<<endl<<"父亲: ";
//  for(int i=1;i<=n;i++) cout<<fa[i]<<" ";
//  cout<<endl<<"当前DFS序对应的值: ";
//  for(int i=1;i<=n;i++) cout<<rnk[i]<<" ";
//  cout<<endl;
    while(m--){
        int op;
        cin>>op;
        if(op==1){
            int x,y,z;
            cin>>x>>y>>z;
            addtree(x,y,z);
        }
        if(op==2){
            int x,y;
            cin>>x>>y;
            cout<<searchtree(x,y)<<endl;
        }
        if(op==3){
            int x,y;
            cin>>x>>y;
            add(1,dfn[x],dfn[x]+siz[x]-1,y%mod);
        }
        if(op==4){
            int x;
            cin>>x;
            cout<<search(1,dfn[x],dfn[x]+siz[x]-1)<<endl;
        }
    }
    return 0;
}

by xyztapeplayer @ 2024-04-26 17:19:03

提交记录


|