zoukankan      html  css  js  c++  java
  • 51Nod 1199 Money out of Thin Air (树链剖分+线段树)

    题目来源: Ural
    基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题
     收藏
     关注
    一棵有N个节点的树,每个节点对应1个编号及1个权值,有2种不同的操作。
    操作1:S x y z,表示如果编号为x的节点的权值 < y,则将节点x的权值加上z。(Single)
    操作2:A x y z,表示如果编号为x的节点以及其所有子节点的权值平均值 < y,则将节点x及其所有子节点的权值加上z。(All)
    给出树节点之间的关系,进行M次操作,问所有操作完成后,各个节点的权值为多少?
    节点的编号为0 - N - 1,根节点的编号为0,并且初始情况下,根节点的权值也是0。
     
    Input
    第1行:2个数N, M,N为节点的数量,M为操作的数量(1 <= N, M <= 50000)。
    第2 - N行:每行描述一个节点N[i]的信息,第2行对应编号为1的节点,第N行对应编号为N - 1的节点。具体内容为:每行2个数P[i], W[i]。P[i]为当前节点的父节点的编号,W[i]为当前节点的权值。(0 <= W[i] <= 10^5, P[i] < i)
    第N + 1 - N + M行:每行表示一个操作,S x y z或A x y z,(0 <= y, z <= 10^5)。
    Output
    输出共N行,每行1个数W[i],表示经过M次后,编号为0 - N - 1的节点的权值。
    Input示例
    4 3
    0 10
    0 10
    1 2
    S 0 1 1
    A 0 20 1
    S 3 2 1
    Output示例
    2
    11
    11
    3

    思路:
    很简单的一道树链剖分+线段树,写起来麻烦点。。代码量有点大,一不小心就打错了。找半天。。

    实现代码:
    #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 = 7e5+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 scan_d ( ll& x , char c = 0 , ll flag = 0 ) {
        while ( ( c = getchar () ) != '-' && ( c < '0' || c > '9' ) ) ;
        if ( c == '-' ) flag = 1 , x = 0 ;
        else x = c - '0' ;
        while ( ( c = getchar () ) >= '0' && c <= '9' ) x = x * 10 + c - '0' ;
        if ( flag ) x = -x ;
    }
    
    
    void pushup(ll rt){
       sum[rt] = sum[rt<<1] + sum[rt<<1|1];
    }
    
    void build(ll l,ll r,ll rt){
        if(l == r){
            sum[rt] = a[rk[l]];
            //cout<<"l: "<<l<<" sum: "<<sum[rt]<<" al: "<<rk[l]<<endl;
            return ;
        }
        mid;
        build(lson);
        build(rson);
        pushup(rt);
    }
    
    void update(ll p,ll c,ll l,ll r,ll rt){
        if(l == r){
            sum[rt] += c;
            return ;
        }
        mid;
        if(p <= m) update(p,c,lson);
        else update(p,c,rson);
        pushup(rt);
    }
    
    void pushdown(ll l,ll r,ll rt){
        if(lazy[rt]){
            mid;
            lazy[rt<<1]+=lazy[rt];
            lazy[rt<<1|1]+=lazy[rt];
            sum[rt<<1]+=lazy[rt]*(m-l+1);
            sum[rt<<1|1]+=lazy[rt]*(r-m);
            lazy[rt] = 0;
        }
    }
    
    ll query(ll L,ll R,ll l,ll r,ll rt){
        if(L <= l&&R >= r){
            return sum[rt];
        }
        //cout<<l<<" "<<r<<endl;
        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;
    }
    
    
    void update1(ll L,ll R,ll c,ll l,ll r,ll rt){
        if(l == r){
            sum[rt]+=c;
            return ;
        }
        if(L <= l&&R >= r){
            sum[rt]+=c*(r-l+1);
            lazy[rt]+=c;
            return ;
        }
        mid;
        pushdown(l,r,rt);
        if(L <= m) update1(L,R,c,lson);
        if(R > m) update1(L,R,c,rson);
        pushup(rt);
    }
    
    ll query1(ll p,ll l,ll r,ll rt){
       if(l == r) return sum[rt];
       pushdown(l,r,rt);
       mid;
       if(p <= m) return query1(p,lson);
       else return query1(p,rson);
    }
    
    int main()
    {
        ios::sync_with_stdio(0);
        cin.tie(0); cout.tie(0);
        ll u,w;
        cin>>n>>m;
        a[0] = 0;
        memset(son,-1,sizeof(son));
        for(ll i = 1;i < n;i ++){
            cin>>u>>w;
            add(u,i);a[i]=w;
        }
        dfs1(0,-1,1); dfs2(0,0); build(0,n-1,1);
        char op;
        ll x,y,z;
        while(m--){
            cin>>op>>x>>y>>z;
            if(op == 'A'){
                ll ans = query(tid[x],mx[x],0,n-1,1);
                double num = ans*1.0/(mx[x]-tid[x]+1);
                if(num < y) update1(tid[x],mx[x],z,0,n-1,1);
            }
            else{
                ll ans = query1(tid[x],0,n-1,1);
                if(ans < y) update(tid[x],z,0,n-1,1);
            }
        }
        for(ll i = 0;i < n;i ++){
            cout<<query1(tid[i],0,n-1,1)<<endl;;
        }
        return ;
    }
  • 相关阅读:
    light oj 1105 规律
    light oj 1071 dp(吃金币升级版)
    light oj 1084 线性dp
    light oj 1079 01背包
    light oj 1068 数位dp
    light oj 1219 树上贪心
    light oj 1057 状压dp TSP
    light oj 1037 状压dp
    矩阵快速幂3 k*n铺方格
    矩阵快速幂2 3*n铺方格
  • 原文地址:https://www.cnblogs.com/kls123/p/9009924.html
Copyright © 2011-2022 走看看