码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces Round #530 (Div. 2) E (树形dp+线段树)

时间:2019-01-13 22:20:35      阅读:230      评论:0      收藏:0      [点我收藏+]

标签:结束   游戏   int   printf   要求   can   main   最大   线段   

链接:

题意:

给你一棵树,树上有n个节点,每个节点上有ai块饼干,在这个节点上的每块饼干需要花费bi时间,有两个玩家,玩家一可以移动到当前点的子节点也可以申请游戏结束返回根节点并吃沿途的饼干,玩家二可以删除当前点到儿子节点的一条边,走路和吃饼干都消耗时间,会给出一个总时间,在总时间内尽可能的多吃饼干,问最多能吃多少个?

思路:

由于是玩家一先手,那么最开始的最大边则不会被删除,但之后路途的最大边都会被玩家二删除,所以我们对于当前点我们需要求:

1.如果现在回头那么最多可以吃到多少饼干

2.向下走最多可以吃到多少饼干

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 = 1e6+10;
const ll Max = 1e6;
struct node{
    ll to,w,next;
}e[M<<1];
ll sum[M<<2],num[M<<2],a[M],tim[M],head[M],cnt;
void add(ll u,ll v,ll w){
    e[++cnt].to = v;e[cnt].next = head[u];e[cnt].w = w;head[u] = cnt;
}

void pushup(ll rt){
    sum[rt] = sum[rt<<1] + sum[rt<<1|1];
    num[rt] = num[rt<<1] + num[rt<<1|1];
}

void update(ll p,ll c,ll l,ll r,ll rt){
    if(l == r){
        sum[rt] += p*c;
        num[rt] += c;
        return ;
    }
    mid;
    if(p <= m) update(p,c,lson);
    else update(p,c,rson);
    pushup(rt);
}

ll query(ll t,ll l,ll r,ll rt){
    if(sum[rt] <= t) return num[rt];
    if(l == r){
        return t/l;
    }
    mid;
    if(sum[rt<<1] >= t) return query(t,lson);
    else return num[rt<<1] + query(t-sum[rt<<1],rson);
}

ll dfs(ll u,ll fa,ll t){
    update(tim[u],a[u],1,Max,1);
    ll f1 = query(t,1,Max,1);
    ll f2 = 0,f3 = 0;

    for(ll i = head[u];i;i=e[i].next){
        ll v = e[i].to;
        if(v == fa) continue;
        if(t <= e[i].w*2) continue;
        ll k = dfs(v,u,t-e[i].w*2);
        if(k > f2) f3 = f2,f2 = k;
        else if(k > f3) f3 = k;

    }
    update(tim[u],-a[u],1,Max,1);
    if(u == 1) return max(f1,f2);
    else return max(f1,f3);
}

int main()
{
    ll n,T,x,y;
    scanf("%lld%lld",&n,&T);
    for(ll i = 1;i <= n;i ++) scanf("%lld",&a[i]);
    for(ll i = 1;i <= n;i ++) scanf("%lld",&tim[i]);
    for(ll i = 2;i <= n;i ++){
        scanf("%lld%lld",&x,&y);
        add(i,x,y); add(x,i,y);
    }
    printf("%lld\n",dfs(1,0,T));
    return 0;
}

 

Codeforces Round #530 (Div. 2) E (树形dp+线段树)

标签:结束   游戏   int   printf   要求   can   main   最大   线段   

原文地址:https://www.cnblogs.com/kls123/p/10264180.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!