• bzoj 4034: [HAOI2015]树上操作 (树剖+线段树 子树操作)


    4034: [HAOI2015]树上操作

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 6779  Solved: 2275
    [Submit][Status][Discuss]

    Description

    有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个
    操作,分为三种:
    操作 1 :把某个节点 x 的点权增加 a 。
    操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
    操作 3 :询问某个节点 x 到根的路径中所有点的点权和。

    Input

    第一行包含两个整数 N, M 。表示点数和操作数。接下来一行 N 个整数,表示树中节点的初始权值。接下来 N-1 
    行每行三个正整数 fr, to , 表示该树中存在一条边 (fr, to) 。再接下来 M 行,每行分别表示一次操作。其中
    第一个数表示该操作的种类( 1-3 ) ,之后接这个操作的参数( x 或者 x a ) 。
     

    Output

    对于每个询问操作,输出该询问的答案。答案之间用换行隔开。

     

    Sample Input

    5 5
    1 2 3 4 5
    1 2
    1 4
    2 3
    2 5
    3 3
    1 2 1
    3 5
    2 1 2
    3 3

    Sample Output

    6
    9
    13

    HINT

     对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不会超过 10^6 。

     
    思路:
    在dfs的时候,加个mx数组,存下每个节点的子节点坐标在线段树中最大的值,那么对以这个点为根节点的子树进行操作是,也就是操作根节点到根节点坐标最大的子节点这段区间,然后就很容易了
    实现代码:
    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define mid ll m = (l + r) >> 1
    const ll M = 2e5+10;
    struct node{
        ll to,next;
    }e[M];
    ll n,m,cnt1,cnt,a[M];
    ll sum[M<<2],lazy[M<<2],son[M],fa[M],head[M],siz[M],top[M],dep[M],tid[M],rk[M],mx[M];
    void add(ll u,ll v){
        e[++cnt1].to = v;e[cnt1].next = head[u];head[u] = cnt1;
        e[++cnt1].to = u;e[cnt1].next = head[v];head[v] = cnt1;
    }
    
    void dfs1(ll u,ll faz,ll deep){
         dep[u] = deep;
         fa[u] = faz;
         siz[u] = 1;
         for(ll i = head[u];i;i=e[i].next){
            ll v = e[i].to;
            if(v != fa[u]){
                dfs1(v,u,deep+1);
                siz[u] += siz[v];
                if(son[u] == -1||siz[v] > siz[son[u]])
                    son[u] = v;
            }
         }
    }
    
    void dfs2(ll u,ll t){
        top[u] = t;
        mx[u] = cnt;
        tid[u] = cnt;
        rk[cnt] = u;
        cnt++;
        if(son[u] == -1) return;
        dfs2(son[u],t),mx[u] = max(mx[u],mx[son[u]]);
        for(ll i = head[u];i;i = e[i].next){
            ll v = e[i].to;
            if(v != son[u]&&v != fa[u])
                dfs2(v,v),mx[u]=max(mx[u],mx[v]);
        }
    }
    
    
    void pushup(ll rt){
        sum[rt] = sum[rt<<1] + sum[rt<<1|1];
    }
    
    void pushdown(ll l,ll r,ll rt){
        if(lazy[rt]){
            mid;
            sum[rt<<1] += lazy[rt]*(m-l+1);
            sum[rt<<1|1] += lazy[rt]*(r - m);
            lazy[rt<<1] += lazy[rt];
            lazy[rt<<1|1] += lazy[rt];
            lazy[rt] = 0;
        }
    }
    
    void build(ll l,ll r,ll rt){
        lazy[rt] = 0;
        if(l == r){
            sum[rt] = a[rk[l]];
            return ;
        }
        mid;
        build(lson);
        build(rson);
        pushup(rt);
    }
    
    void update(ll L,ll R,ll c,ll l,ll r,ll rt){
        if(L <= l&&R >= r){
            sum[rt] += c*(r-l+1);
            lazy[rt]+=c;
            return ;
        }
        pushdown(l,r,rt);
        mid;
        if(L <= m) update(L,R,c,lson);
        if(R > m) update(L,R,c,rson);
        pushup(rt);
    }
    
    ll query(ll L,ll R,ll l,ll r,ll rt){
        if(L <= l&&R >= r){
            return sum[rt];
        }
        pushdown(l,r,rt);
        mid;
        ll ret = 0;
        if(L <= m) ret += query(L,R,lson);
        if(R > m) ret += query(L,R,rson);
        return ret;
    }
    
    ll ask(ll x,ll y){
        ll ans = 0;
        ll fx = top[x],fy = top[y];
        while(fx != fy){
            if(dep[fx] < dep[fy]) swap(x,y),swap(fx,fy);
            ans += query(tid[fx],tid[x],1,n,1);
            x = fa[fx];fx=top[x];
        }
        if(dep[x] > dep[y]) swap(x,y);
        ans += query(tid[x],tid[y],1,n,1);
        return ans;
    }
    
    int main()
    {
        ll u,v,x,y,z;
        scanf("%lld%lld",&n,&m);
        cnt1 = 0;cnt = 1;
        memset(son,-1,sizeof(son));
        for(ll i = 1;i <= n;i ++){
            scanf("%lld",&a[i]);
        }
        for(ll i = 0;i < n-1;i++){
            scanf("%lld%lld",&u,&v);
            add(u,v);
        }
        dfs1(1,0,1);dfs2(1,1),build(1,n,1);
        while(m--){
            scanf("%lld%lld",&x,&y);
            if(x==1){
                scanf("%lld",&z);
                update(tid[y],tid[y],z,1,n,1);
            }
            else if(x == 2){
                scanf("%lld",&z);
                update(tid[y],mx[y],z,1,n,1);
            }
            else{
                printf("%lld
    ",ask(1,y));
            }
        }
        return 0;
    }
  • 相关阅读:
    Confluo: Distributed Monitoring and Diagnosis Stack for High-speed Networks
    kubernetes in action
    kubernetes in action
    kubernetes in action
    kubernetes in action
    kubernetes in action
    Kafka: Exactly-once Semantics
    Reinforcement Learning
    unity的 Social API
    hdu 4336 概率dp + 状压
  • 原文地址:https://www.cnblogs.com/kls123/p/8986378.html
Copyright © 2020-2023  润新知