UVA1674 闪电的能量 Lightning Energy Report 题解

题目传送门

前置知识

树链剖分 | 线段树

解法

树链剖分后维护一个支持区间修改,单点查询的线段树即可。

也可以树上差分,同 146. DFS 序 3,树上差分 1\(1,2\) 操作,时间复杂度比树链剖分更优。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define ull unsigned long long
#define sort stable_sort 
#define endl '\n'
struct node
{
    int nxt,to;
}e[100010];
int head[100010],c[100010],cc[100010],siz[100010],fa[100010],dep[100010],son[100010],top[100010],dfn[100010],cnt=0,tot=0;
struct SMT
{
    struct SegmentTree
    {
        int l,r,sum,lazy;
    }tree[200010];
    int lson(int x)
    {
        return x*2;
    }
    int rson(int x)
    {
        return x*2+1;
    }
    void pushup(int rt)
    {
        tree[rt].sum=tree[lson(rt)].sum+tree[rson(rt)].sum;
    }
    void build(int rt,int l,int r)
    {
        tree[rt].l=l;
        tree[rt].r=r;
        tree[rt].lazy=0;
        if(l==r)
        {
            tree[rt].sum=cc[l];
            return;
        }
        int mid=(l+r)/2;
        build(lson(rt),l,mid);
        build(rson(rt),mid+1,r);
        pushup(rt);
    }
    void pushdown(int rt)
    {
        if(tree[rt].lazy!=0)
        {
            tree[lson(rt)].sum+=tree[rt].lazy*(tree[lson(rt)].r-tree[lson(rt)].l+1);
            tree[rson(rt)].sum+=tree[rt].lazy*(tree[rson(rt)].r-tree[rson(rt)].l+1);
            tree[lson(rt)].lazy+=tree[rt].lazy;
            tree[rson(rt)].lazy+=tree[rt].lazy;
            tree[rt].lazy=0;
        }
    }
    void update(int rt,int x,int y,int val)
    {
        if(x<=tree[rt].l&&tree[rt].r<=y)
        {
            tree[rt].sum+=val*(tree[rt].r-tree[rt].l+1);
            tree[rt].lazy+=val;
            return;
        }
        pushdown(rt);
        int mid=(tree[rt].l+tree[rt].r)/2;
        if(x<=mid)
        {
            update(lson(rt),x,y,val);
        }
        if(y>mid)
        {
            update(rson(rt),x,y,val);
        }
    }
    int query(int rt,int x,int y)
    {
        if(x<=tree[rt].l&&tree[rt].r<=y)
        {
            return tree[rt].sum;
        }
        pushdown(rt);
        int mid=(tree[rt].l+tree[rt].r)/2,ans=0;
        if(x<=mid)
        {
            ans+=query(lson(rt),x,y);
        }
        if(y>mid)
        {
            ans+=query(rson(rt),x,y);
        }
        return ans;
    }
}T;
void add(int u,int v)
{
    cnt++;
    e[cnt].nxt=head[u];
    e[cnt].to=v;
    head[u]=cnt;
}
void dfs1(int x,int father)
{
    siz[x]=1;
    fa[x]=father;
    dep[x]=dep[father]+1;
    for(int i=head[x];i!=0;i=e[i].nxt)
    {
        if(e[i].to!=father)
        {
            dfs1(e[i].to,x);
            siz[x]+=siz[e[i].to];
            son[x]=(siz[e[i].to]>siz[son[x]])?e[i].to:son[x];
        }
    }
}
void dfs2(int x,int father,int id)
{
    top[x]=id;
    tot++;
    dfn[x]=tot;
    cc[tot]=c[x];
    if(son[x]!=0)
    {
        dfs2(son[x],x,id);
        for(int i=head[x];i!=0;i=e[i].nxt)
        {
            if(e[i].to!=father&&e[i].to!=son[x])
            {
                dfs2(e[i].to,x,e[i].to);
            }
        }
    }
}
void update1(int u,int v,int val)
{
    while(top[u]!=top[v])
    {
        if(dep[top[u]]>dep[top[v]])
        {
            T.update(1,dfn[top[u]],dfn[u],val);
            u=fa[top[u]];
        }
        else
        {
            T.update(1,dfn[top[v]],dfn[v],val);
            v=fa[top[v]];
        }
    }
    if(dep[u]<dep[v])
    {
        T.update(1,dfn[u],dfn[v],val);
    }
    else
    {
        T.update(1,dfn[v],dfn[u],val);
    }
}
int query1(int pos)
{
    return T.query(1,dfn[pos],dfn[pos]);
}
int main()
{
    int t,n,m,u,v,w,i,j;
    cin>>t;
    for(j=1;j<=t;j++)
    {
        cnt=tot=0;
        memset(e,0,sizeof(e));
        memset(head,0,sizeof(head));
        memset(son,0,sizeof(son));
        cin>>n;
        for(i=1;i<=n-1;i++)
        {
            cin>>u>>v;
            u++;
            v++;
            add(u,v);
            add(v,u);
        }
        dfs1(1,0);
        dfs2(1,0,1);
        T.build(1,1,n);
        cin>>m;
        for(i=1;i<=m;i++)
        {
            cin>>u>>v>>w;
            u++;
            v++;
            update1(u,v,w);
        }
        cout<<"Case #"<<j<<":"<<endl;
        for(i=1;i<=n;i++)
        {
            cout<<query1(i)<<endl;
        }
    }
    return 0;
}
posted @ 2024-05-26 11:26  hzoi_Shadow  阅读(4)  评论(0编辑  收藏  举报
扩大
缩小