【题解】hdu5692(2018-07-28校赛 线段树入门2 D)线段树+dfs序

题目

题目链接

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define lc o<<1
#define rc o<<1|1
typedef long long ll;
const int N=1e5+10;
int in[N<<1],out[N<<1],head[N],pre[N];
ll sum[N<<2],lazy[N<<2],val[N],a[N<<1],dis[N];
struct Edge{
    int v,nx;
}edge[N<<1];
int t,m,n,tot,num;
inline void addedge(int u,int v)
{
    edge[tot].v=v;
    edge[tot].nx=head[u];
    head[u]=tot++;
}
void dfs(int u,int fa)
{
    in[u]=++num;
    a[num]=dis[u];
    for(int i=head[u];~i;i=edge[i].nx)
    {
        int v=edge[i].v;
        if(v==fa)continue;
        dis[v]=dis[u]+val[v];
        dfs(v,u);
    }
    out[u]=num;
}
inline void push_up(int o){sum[o]=max(sum[lc],sum[rc]);}
void build(int o,int l,int r)
{
    lazy[o]=0; 
    if(l==r){sum[o]=a[l];return;}
    int mid=l+r>>1;
    build(lc,l,mid);build(rc,mid+1,r);
    push_up(o);
}
inline void push_down(int o,int l,int r)
{
    if(!lazy[o])return;
    sum[lc]+=lazy[o];
    lazy[lc]+=lazy[o];
    sum[rc]+=lazy[o];
    lazy[rc]+=lazy[o];
    lazy[o]=0;
}
ll query(int o,int l,int r,int nl,int nr)
{
    if(nl<=l&&r<=nr)return sum[o];
    push_down(o,l,r);
    int mid=l+r>>1;
    if(nr<=mid)return query(lc,l,mid,nl,nr);
    else if(nl>mid)return query(rc,mid+1,r,nl,nr);
    return max(query(lc,l,mid,nl,mid),query(rc,mid+1,r,mid+1,nr));
}
void update(int o,int l,int r,int nl,int nr,ll v)
{
    if(nl<=l&&r<=nr)
    {
        sum[o]+=v;
        lazy[o]+=v;
        return;
    }
    push_down(o,l,r);
    int mid=l+r>>1;
    if(nr<=mid)update(lc,l,mid,nl,nr,v);
    else if(nl>mid)update(rc,mid+1,r,nl,nr,v);
    else update(lc,l,mid,nl,mid,v),update(rc,mid+1,r,mid+1,nr,v);
    push_up(o);
}
int main()
{
    //freopen("in.txt","r",stdin);
    scanf("%d",&t);
    for(int ca=1;ca<=t;ca++)
    {
        memset(head,-1,sizeof(head));
        num=0;
        tot=0;
        printf("Case #%d:\n",ca);
        scanf("%d%d",&n,&m);
        int u,v;
        for(int i=1;i<n;i++)scanf("%d%d",&u,&v),addedge(u,v),addedge(v,u);
        for(int i=0;i<n;i++)scanf("%lld",&val[i]);
        dis[0]=val[0];
        dfs(0,0);
        build(1,1,num);
        int op,x;
        ll y;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&op,&x);
            if(op)printf("%lld\n",query(1,1,num,in[x],out[x]));
            else scanf("%lld",&y),update(1,1,num,in[x],out[x],y-val[x]),val[x]=y;
        }
    }
    return 0;
}

总结

dfs序是一段区间,可以用线段树的区间修改维护。
线段树用法挺灵活的,已经见过的用法有求区间和、区间最值、平方和、立方和、区间开根号、区间整除、区间取模、区间最大公约数、真子集、dfs序上的维护。

猜你喜欢

转载自blog.csdn.net/qq_41958841/article/details/82377487
今日推荐