Wannafly挑战赛21 E 未来城市规划

Wannafly挑战赛21 E 未来城市规划


https://www.nowcoder.com/acm/contest/159/E

数据结构好题orz

先看看一条边在一个子树里的贡献,就是这条边的权值×一边的点数×另一边的点数

设子树的树根是\(x\),这条边连接的深度较大的点是\(y\)

那么贡献就是\(W(siz_y)(siz_x-siz_y)\)

\(W(siz_xsiz_y-siz_y^2)\)

边权放到点上,对每个点维护\(Wsiz\)\(Wsiz^2\)即可。

注意nowcoder的clang++非常锅锅,尽量开全局变量,不然main里的n可能就随便从5变成67了(调了1h mmp)

#include<bits/stdc++.h>
#define il inline
#define vd void
#define mod 2019
typedef long long ll;
il int gi(){
    int x=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return x*f;
}
int W[50010];
int fir[50010],dis[50010],nxt[50010],id;
il vd link(int a,int b){nxt[++id]=fir[a],fir[a]=id,dis[id]=b;}
int dfn[50010],redfn[50010],siz[50010],son[50010],dep[50010],fa[50010];
il vd dfs1(int x){
    siz[x]=1;
    for(int i=fir[x];i;i=nxt[i]){
        dep[dis[i]]=dep[x]+1;
        dfs1(dis[i]);
        siz[x]+=siz[dis[i]];
        if(siz[dis[i]]>siz[son[x]])son[x]=dis[i];
    }
}
int top[50010];
il vd dfs2(int x,int tp){
    dfn[x]=++dfn[0];redfn[dfn[0]]=x;
    top[x]=tp;
    if(son[x])dfs2(son[x],tp);
    for(int i=fir[x];i;i=nxt[i])if(dis[i]!=son[x])dfs2(dis[i],dis[i]);
}
int s1[200010],s2[200010],S1[200010],S2[200100],lz[200010];
#define mid ((l+r)>>1)
il vd Inc(int x,const int&t){
    S1[x]=(S1[x]+s1[x]*t)%mod;
    S2[x]=(S2[x]+s2[x]*t%mod)%mod;
    lz[x]=(lz[x]+t)%mod;
}
il vd down(const int&x){if(lz[x])Inc(x<<1,lz[x]),Inc(x<<1|1,lz[x]),lz[x]=0;}
il vd upd(const int&x){
    S1[x]=S1[x<<1]+S1[x<<1|1];
    S2[x]=S2[x<<1]+S2[x<<1|1];
}
il vd build(int x,int l,int r){
    if(l==r){
        int p=redfn[l];
        s1[x]=siz[p],s2[x]=siz[p]*siz[p]%mod;
        S1[x]=s1[x]*W[p]%mod,S2[x]=s2[x]*W[p]%mod;
        return;
    }
    build(x<<1,l,mid),build(x<<1|1,mid+1,r);
    upd(x);
    s1[x]=(s1[x<<1]+s1[x<<1|1])%mod;
    s2[x]=(s2[x<<1]+s2[x<<1|1])%mod;
}
il vd update(int x,int l,int r,const int&L,const int&R,const int&d){
    if(L<=l&&r<=R)return Inc(x,d);
    down(x);
    if(L<=mid)update(x<<1,l,mid,L,R,d);
    if(mid<R)update(x<<1|1,mid+1,r,L,R,d);
    upd(x);
}
il std::pair<int,int> operator +(const std::pair<int,int>&a,const std::pair<int,int>&b){return std::make_pair(a.first+b.first,a.second+b.second);}
il std::pair<int,int> query(int x,int l,int r,const int&L,const int&R){
    if(L<=l&&r<=R)return std::make_pair(S1[x],S2[x]);
    down(x);
    if(L<=mid)
        if(mid<R)return query(x<<1,l,mid,L,R)+query(x<<1|1,mid+1,r,L,R);
        else return query(x<<1,l,mid,L,R);
    else return query(x<<1|1,mid+1,r,L,R);
}
int n,q;
int main(){
    n=gi(),q=gi();
    for(int i=2;i<=n;++i)fa[i]=gi(),W[i]=gi(),link(fa[i],i);
    dfs1(1),dfs2(1,1);
    build(1,1,n);
    char opt[2];int u,v,w;
    while(q--){
        scanf("%s",opt);
        if(opt[0]=='I'){
            u=gi(),v=gi(),w=gi();
            if(u==v)continue;
            while(top[u]!=top[v]){
                if(dep[top[u]]>dep[top[v]])update(1,1,n,dfn[top[u]],dfn[u],w),u=fa[top[u]];
                else update(1,1,n,dfn[top[v]],dfn[v],w),v=fa[top[v]];
            }
            if(dfn[u]>dfn[v])std::swap(u,v);
            update(1,1,n,dfn[u]+1,dfn[v],w);
        }else{
            w=gi();
            if(siz[w]==1){puts("0");continue;}
            std::pair<int,int>A=query(1,1,n,dfn[w]+1,dfn[w]+siz[w]-1);
            A.first%=mod,A.second%=mod;
            printf("%d\n",(A.first*siz[w]-A.second+mod)%mod);
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/xzz_233/p/9721143.html