• hdu 5692 dfs序 线段树


    题目概括

    给定一棵n个点的有根树,每个点有一个点权。根节点为0,节点标号为0~n-1。

    定义最大路径为:从根出发走到某个点,点权和最大的路径。

    现在有Q次操作,每种是以下两种之一:

    (1).将点x的点权变成v。

    (2).求经过某一个点的最大路径的点权和

    参考博客 http://www.cnblogs.com/zhouzhendong/p/7263838.html

    思路:

    w[x]为节点x的权值     Dis[x]为从根节点到达当前节点的权值

    那么,一开始,dis[x]可以通过一遍dfs全部求出来。

    如何处理更改和询问呢?那么我们从询问入手

    题目询问的是经过一个点的最大路径的点权和,那么其实就是到达这个节点或者其子孙节点的最大dis[x], 其实就是查询整个子树的max(dis[x])

      在树的dfs序中,同一个子树节点的所对应的序号一定是整个dfs序中的连续的一段!

    那么我们就可以把询问转化成“求区间最大值”的问题了。然而同理思考,那么修改其实就是修改整个子树的最大值!对于0 x y, 其实就是子树x的所有节点都增加y-w[x]!那么最大值也增加y-w[x]。

    问题就变成了一个询问区间最大值和区间修改(同增或者同减)的问题了。

    #include<bits/stdc++.h>
    using namespace std;
    
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define ll long long
    #define lson l,mid,rt<<1
    #define rson mid+1,r,rt<<1|1
    
    const int N = 1E5+3;
    const int M = 1E5+3;
    const ll LINF = 1e17+3;
    
    
    int n,m;
    ll tmax[N<<2],col[N<<2];
    int vis[N], tim,in[N],out[N];
    ll v[N],d[N];
    vector<int>V[N];
    //距离d[N]需要注意   因为这里的1..n不是表示点1..n 而是dfs序的1..n
    void dfs(int pre,int t){
        int len = V[t].size();
        in[t]=++tim;
        d[in[t]]  = d[in[pre]]+v[t];
        for(int i=0;i<len;++i){
            if(vis[V[t][i]])continue;
            vis[V[t][i]]=1;
            dfs(t,V[t][i]);
        }
        out[t]=tim;
    }
    
    
    void pushup(int rt){
        tmax[rt] = max(tmax[rt<<1],tmax[rt<<1|1]);
    }
    void pushdown(int rt,int len){
        if(col[rt]){
            col[rt<<1] +=col[rt];
            col[rt<<1|1]+=col[rt];
            tmax[rt<<1]+=col[rt];
            tmax[rt<<1|1]+=col[rt];
            col[rt]=0;
        }
    }
    
    void build(int l,int r,int rt){
        col[rt] = 0;
        if(l==r){
            tmax[rt] = d[l]; return ;
        }
        int mid = (l+r)/2;
        build(lson);build(rson);
        pushup(rt);
    }
    void update(int l,int r,int rt,int a,int b ,ll val){
        if(a<=l && b>=r){
            col[rt]+=val;
            tmax[rt]+=val;
            return ;
        }
        pushdown(rt,r-l+1);
        int mid =(l+r)/2;
        if(a<=mid)update(lson,a,b,val);
        if(b>mid)update(rson,a,b,val);
        pushup(rt);
    }
    ll query(int l,int r,int rt,int a,int b){
        if(a<=l && b>=r){
            return tmax[rt];
        }
        int mid =(l+r)/2;
        pushdown(rt,r-l+1);
        ll ans= -LINF;
        if(a<=mid)
            ans = max(ans, query(lson,a,b));
        if(b>mid)
            ans = max(ans,query(rson,a,b));
        return ans;
    }
    
    int main(){
    
        int t;
    
        cin>>t;
        int cnt=1;
    
            while(t--){
                tim= 0 ;
                memset(vis,0,sizeof(vis));
                memset(col,0,sizeof(col));
                scanf("%d %d",&n,&m);
                for(int i=0;i<=n;++i)V[i].clear();
    
                for(int i=1;i<n;++i){
                    int u,v;
                    scanf("%d %d",&u,&v);
                    u++;v++;
                    V[u].pb(v);
                    V[v].pb(u);
                }
                for(int i=1;i<=n;++i){
                    scanf("%lld",&v[i]); d[i]=v[i];
                }
    
                vis[1]=1;
                d[0]=0;
                dfs(0,1);
                build(1,n,1);
    
                printf("Case #%d:
    ",cnt++);
                while(m--){
                    int c,x;ll y;
                    scanf("%d",&c);
                    if(c==0){
                        //修改  成Y   也就是将x以及所有子树修改成Y  也就是增加 y-v[x] , v[x]=y;
                        scanf("%d %lld",&x,&y);x++;
                        update(1,n,1,in[x],out[x],y-v[x]);
                        v[x]=y;
                    }
                    else {
                        //询问到x
                        scanf("%d",&x);x++;
                        printf("%lld
    ",query(1,n,1,in[x],out[x]));
                    }
                }
            }
        return 0;
    }
  • 相关阅读:
    Springboot + Caffeine 实现本地缓存
    springboot + mybatis-plus + sharding-jdbc 实现单库分表
    工厂模式+策略模式 使用
    JAVA 金额自动除以100,精确到分
    spring aop + 自定义注解实现本地缓存
    springboot 使用 retry重试机制
    Mybatis-plus 自动注入公共字段
    docker 安装kafka
    ES 实现聚合分页
    Authentication token manipulation error 及 mongodb WiredTigerLAS.wt 文件过大问题
  • 原文地址:https://www.cnblogs.com/wjhstudy/p/9827238.html
Copyright © 2020-2023  润新知