HDU5692 Snacks 树上DFS序+线段树

HDU5692 Snacks

无向图 G = (Vn,En-1)构成一棵树,因此根节点O到树上各个节点的路径唯一,用线段树维护各个节点到O节点的权值之和(称为x的前缀和),每个节点的权值变化影响它和它子树的前缀和。

DFS先序遍历初始化各点的前缀和并储存在线段树中,对于每个节点x的变化,更新x和x子树的前缀和。(DFS先序遍历序列中属于同一子树的节点在连续区间中)

DFS序可以有效处理子树变化问题,把树上的统计问题转化为区间统计问题并用线段树和树状数组维护。---引申---树链剖分

#include<bits/stdc++.h>
using namespace std;
const int MAX=1e5+5;
const long long INF=1e18;
struct Edge
{
    int to,nxt;
}edge[MAX*2];
int head[MAX],tot;
int val[MAX];
long long val_[MAX];
long long a[MAX*4],lazy[MAX*4];
int l[MAX],r[MAX],nd[MAX],cnt;
void init()
{
    tot=0;cnt=0;
    memset(head,-1,sizeof(head));
}
void addedge(int x,int y)
{
    edge[tot].to=y;
    edge[tot].nxt=head[x];
    head[x]=tot++;
    edge[tot].to=x;
    edge[tot].nxt=head[y];
    head[y]=tot++;
}
void pushup(int rt)
{
    a[rt]=max(a[rt*2],a[rt*2+1]);
}
void pushdown(int rt)
{
    a[rt*2]+=lazy[rt];
    a[rt*2+1]+=lazy[rt];
    lazy[rt*2]+=lazy[rt];
    lazy[rt*2+1]+=lazy[rt];
    lazy[rt]=0;
}
void build(int rt,int l,int r)
{
    lazy[rt]=0;
    if(l==r)
    {
        a[rt]=val_[nd[l]];
        return ;
    }
    int mid=(l+r)>>1;
    build(rt*2,l,mid);
    build(rt*2+1,mid+1,r);
    pushup(rt);
}
void update(int rt,int l,int r,int L,int R,int val)
{
    if (L<=l&&R>=r){a[rt]+=val;lazy[rt]+=val;return ;}
    if (lazy[rt]) pushdown(rt);
    int mid=(l+r)>>1;
    if (L<=mid) update(rt*2,l,mid,L,R,val);
    if (R>mid) update(rt*2+1,mid+1,r,L,R,val);
    pushup(rt);
}
long long query(int rt,int l,int r,int L,int R)//区间查询
{
    if(L<=l&&R>=r)return a[rt];
    if(lazy[rt]) pushdown(rt);
    int mid=(l+r)>>1;
    long long sum=-INF;
    if(L<=mid) sum=max(sum,query(rt*2,l,mid,L,R));
    if(R>mid) sum=max(sum,query(rt*2+1,mid+1,r,L,R));
    return sum;
}
void dfs(int x,int fa)
{
    l[x]=++cnt;
    nd[cnt]=x;
    for(int i=head[x];i!=-1;i=edge[i].nxt)
    {
        int k=edge[i].to;
        if(k!=fa)
        {
            val_[k]=val_[x]+val[k];
            dfs(k,x);
        }
    }
    r[x]=cnt;
}
int main()
{
    int t,n,m,x,y;
    scanf("%d",&t);
    for(int tc=1;tc<=t;tc++)
    {
        init();
        scanf("%d %d",&n,&m);
        for(int i=0;i<n-1;i++)
        {
            scanf("%d %d",&x,&y);
            addedge(x,y);
        }
        for(int i=0;i<n;i++) scanf("%d",&val[i]);
        val_[0]=val[0];dfs(0,-1);
        build(1,1,n);
        printf("Case #%d:\n", tc);
        while(m--)
        {
            scanf("%d",&x);
            if(x==0)
            {
                scanf("%d %d",&x,&y);
                update(1,1,n,l[x],r[x],y-val[x]);
                val[x]=y;
            }
            else
            {
                scanf("%d",&x);
                printf("%I64d\n",query(1,1,n,l[x],r[x]));
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Nrtostp/article/details/81393562
今日推荐