1 条题解

  • 0
    @ 2025-10-8 16:51:50
    #include<bits/stdc++.h>
    using namespace std;
    #define eb emplace_back
    #define LL long long
    template<typename T> void qr(T& x)
    {
        char c=getchar(); x=0; int f=1;
        for(; !isdigit(c); c=getchar()) if(c=='-') f=-1;
        for(; isdigit(c); c=getchar()) x=x*10+(c-'0');
        x*=f;
    }
    template<typename T> void qw(T x)
    {
        if(x<0) putchar('-'), x=-x;
        if(x/10) qw(x/10);
        putchar(x%10+'0'); 
    }
    
    const int N=1e6+10;
    vector<int> G[N]; 
    int n;LL v[N];
    
    int fa[N], siz[N], dep[N], son[N];
    void dfs1(int x, int xfa)
    {
        fa[x]=xfa; 
        dep[x]=dep[xfa]+1; 
    
        siz[x]=1; 
        son[x]=0; 
        for(int y: G[x]) if(y!=xfa)
        {
            dfs1(y, x);
            siz[x]+=siz[y];
            if(siz[y]>siz[son[x]]) son[x]=y;
        }
    }
    
    int tsp, dfn[N], top[N];
    void dfs2(int x, int tp) {
        dfn[x]=++tsp; top[x]=tp;
        if(son[x]) dfs2(son[x], tp);
        for(int y: G[x]) if(y!=son[x] && y!=fa[x])
            dfs2(y, y);
    }
    
    int LCA(int x,int y)
    {
        for(;top[x]!=top[y];x=fa[top[x]])if(dep[top[x]]<dep[top[y]])swap(x, y);
    	return dep[x]<dep[y] ? x : y;
    }
    
    LL c1[N], c2[N];
    void add(LL c[], int x, LL k){if(x==0) return ;for(; x<=n; x+=x&-x) c[x]+=k;}
    LL sum(LL c[], int x){LL res=0;for(; x>=1; x-=x&-x) res+=c[x];return res;}
    LL getsum(LL c[], int l, int r){return sum(c, r)-sum(c, l-1);}
    
    int main()
    {
        int m,rt; qr(n),qr(m),qr(rt);
        for(int i=1; i<=n; i++)qr(v[i]);
        for(int i=1, x, y; i<n; i++) qr(x),qr(y),G[x].eb(y), G[y].eb(x);
    
        dep[0]=0;
        dfs1(rt, 0); 
        
        tsp=0;
        dfs2(rt, rt);
    
        for(int i=1; i<=n; i++) 
        {
            add(c1, dfn[i],      v[i]);   add(c2, dfn[i],      v[i]*dep[i]    );
            add(c1, dfn[fa[i]], -v[i]);   add(c2, dfn[fa[i]], -v[i]*dep[fa[i]]);
        }
    
        while(m--)
        {
            int op; scanf("%d", &op);
            if(op==1)      //1 x y k,表示将「结点 x 到结点 y 的简单路径」上所有结点的权值都增加 k
            {
                int x, y; LL k; qr(x); qr(y); qr(k);
                int lca=LCA(x, y), flca=fa[lca];
                add(c1,   dfn[x], k);    add(c2,   dfn[x],  k*dep[x]   );
                add(c1,   dfn[y], k);    add(c2,   dfn[y],  k*dep[y]   );
                add(c1, dfn[lca],-k);    add(c2, dfn[lca], -k*dep[lca] );
                add(c1,dfn[flca],-k);    add(c2,dfn[flca], -k*dep[flca]);
            }
            else if(op==2) //2 x,表示求结点 x 的权值
            {
                int x; qr(x);
                int l=dfn[x], r=dfn[x]+siz[x]-1;
                qw( getsum(c1, l, r) );
                printf("\n");
            }
            else           //3 x,表示求 x 的子树上所有结点的权值之和
            {
                int x; qr(x);
                int l=dfn[x], r=dfn[x]+siz[x]-1;
                qw( getsum(c2, l, r)-getsum(c1, l, r)*(dep[x]-1) );
                printf("\n");
            }
        }
        return 0;
    }
    
    • 1

    *【树上点差分】树结构路径修改、区间求和[LOJ146]DFS序3

    信息

    ID
    649
    时间
    2000ms
    内存
    256MiB
    难度
    8
    标签
    递交数
    213
    已通过
    34
    上传者