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

题:https://codeforces.com/contest/1099/problem/F

题意:给定一个树,每个节点有俩个信息x和t,分别表示这个节点上的饼干个数和先手吃掉这个节点上一个饼干的的时间。然后有先手和后手俩个人。

   ?先手可以这么操作:在规定总时间T到达某个节点然后一定要返回根节点1,期间可以选择吃掉某些节点上的某些饼干(前提是保证剩下的时间能够回到根节点);

   ?后手可以这么操作:在先手到达的位置和这个位置的孩子之间的连边选择一条让先手吃得更多的边摧毁掉,也可以跳过这个过程; 

   问:在给定的总时间T内,先手最多能吃到多少的饼干。

分析:对于每个节点都有3个选择,我们记为dp1,dp2,dp3;

   dp1:从当前位置上去能吃到的最多的饼干;

   dp2:从当前位置沿孩子下去能吃到的最多的饼干数;(这一步只在当前位置为根节点的时候起作用,因为是先手,所以可以直接选最大)

   dp3:从当前位置沿孩子下去能吃到的次多的饼干数;(因为后手会阻止先手吃最大的饼干数,所以就选次大)

   dfs处理这棵树,回溯的时候做dp2,dp3的计算即可;

   然后饼干数的最大和次大我们把节点信息的x和t,全部转化为时间消耗,x*t对应吃了x个饼干,然后二分出答案即可。

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define lson root<<1,l,midd
#define rson root<<1|1,midd+1,r
typedef long long ll;
const int M=1e6+5;
ll x[M],t[M];
struct node{
    int u;
    ll w;
};
vector<node>g[M];
struct Node{
    ll ti,num;
}tree[M<<2];
int n;
void update(ll num,ll ti,ll root,ll l,ll r){
    if(l==r){
        tree[root].ti+=num*ti;
        tree[root].num+=num;
        return ;
    }
    int midd=(l+r)>>1;
    if(ti<=midd)
        update(num,ti,lson);
    else
        update(num,ti,rson);
    tree[root].ti=tree[root<<1].ti+tree[root<<1|1].ti;
    tree[root].num=tree[root<<1].num+tree[root<<1|1].num;
}
ll query(ll nowti,ll root,ll l,ll r){
    if(tree[root].ti<=nowti)
        return tree[root].num;
    if(l==r)
        return nowti/l;
    int midd=(l+r)>>1;
    if(tree[root<<1].ti>=nowti)
        return query(nowti,lson);
    else
        return query(nowti-tree[root<<1].ti,rson)+tree[root<<1].num;
}
ll dfs(int u,ll nowt){
    //cout<<u<<endl;
    update(x[u],t[u],1,1,1000000);
    ll dp1=query(nowt,1,1,1000000);
    ll dp2=0,dp3=0;
    for(int i=0;i<g[u].size();i++){
        node v=g[u][i];
        if(nowt<=2*v.w)
            continue;
        ll temp=dfs(v.u,nowt-2ll*v.w);
        if(temp>dp2)
            dp3=dp2,dp2=temp;
        else if(dp3<temp)
            dp3=temp;
    }
    update(-x[u],t[u],1,1,1000000);
    if(u==1)///根节点,先走,所以不用考虑次大
        return max(dp1,dp2);
    else
        return max(dp1,dp3);
}
int main(){
    ll T;
    scanf("%d%I64d",&n,&T);
    for(int i=1;i<=n;i++)
        scanf("%I64d",&x[i]);
    for(int i=1;i<=n;i++)
        scanf("%I64d",&t[i]);
    for(int i=2;i<=n;i++){
        ll w;
        int u;
        scanf("%d%I64d",&u,&w);
        g[u].pb(node{i,w});
    }
    printf("%I64d",dfs(1,T));
    return 0;
}

原文地址:https://www.cnblogs.com/starve/p/12003889.html

时间: 2024-10-26 03:52:48

Codeforces Round #530 (Div. 2)F Cookies (树形dp+线段树)的相关文章

Codeforces Round #590 (Div. 3) D. Distinct Characters Queries(线段树, 位运算)

链接: https://codeforces.com/contest/1234/problem/D 题意: You are given a string s consisting of lowercase Latin letters and q queries for this string. Recall that the substring s[l;r] of the string s is the string slsl+1-sr. For example, the substrings

Codeforces Round #149 (Div. 2) E. XOR on Segment (线段树成段更新+二进制)

题目链接:http://codeforces.com/problemset/problem/242/E 给你n个数,m个操作,操作1是查询l到r之间的和,操作2是将l到r之间的每个数xor与x. 这题是线段树成段更新,但是不能直接更新,不然只能一个数一个数更新.这样只能把每个数存到一个数组中,长度大概是20吧,然后模拟二进制的位操作.仔细一点就行了. 1 #include <iostream> 2 #include <cstdio> 3 #include <cmath>

Codeforces Round #310 (Div. 1) C. Case of Chocolate (线段树)

题目地址:传送门 这题虽然是DIV1的C..但是挺简单的..只要用线段树分别维护一下横着和竖着的值就可以了,先离散化再维护.每次查找最大的最小值<=tmp的点,可以直接在线段树里搜,也可以二分去找. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.

Codeforces Round #207 (Div. 1) A. Knight Tournament (线段树离线)

题目:http://codeforces.com/problemset/problem/356/A 题意:首先给你n,m,代表有n个人还有m次描述,下面m行,每行l,r,x,代表l到r这个区间都被x所击败了(l<=x<=r),被击败的人立马退出游戏让你最后输出每个人是被谁击败的,最后那个胜利者没被 人击败就输出0 思路:他的每次修改的是一个区间的被击败的人,他而且只会记录第一次那个被击败的人,用线段树堕落标记的话他会记录最后一次的,所以我们倒着来修改, 然后因为那个区间里面还包含了自己,在线段

Codeforces Round #362 (Div. 1) B. Puzzles 树形dp,概率

题目链接: http://codeforces.com/problemset/problem/696/B 题意: 一个树,dfs遍历子树的顺序是随机的.所对应的子树的dfs序也会不同.输出每个节点的dfs序的期望 思路: http://www.cnblogs.com/01world/p/5795498.html 假设四个子节点为A,B,C,D,因为排列等可能,所以A在B前面的概率跟A在B后面的概率相等,C和D对于A而言一样.所以遍历A的时间期望就是( t(B) + t(C) + t(D) )/2

Codeforces Round #603 (Div. 2) F. Economic Difficulties dp

F. Economic Difficulties An electrical grid in Berland palaces consists of 2 grids: main and reserve. Wires in palaces are made of expensive material, so selling some of them would be a good idea! Each grid (main and reserve) has a head node (its num

Codeforces Round #225 (Div. 2)---E. Propagating tree(时间戳+线段树)

Iahub likes trees very much. Recently he discovered an interesting tree named propagating tree. The tree consists of n nodes numbered from 1 to n, each node i having an initial value ai. The root of the tree is node 1. This tree has a special propert

Codeforces Round #337 (Div. 2) D. Vika and Segments 线段树 矩阵面积并

D. Vika and Segments Vika has an infinite sheet of squared paper. Initially all squares are white. She introduced a two-dimensional coordinate system on this sheet and drew n black horizontal and vertical segments parallel to the coordinate axes. All

Codeforces Round #486 (Div. 3) F. Rain and Umbrellas

Codeforces Round #486 (Div. 3) F. Rain and Umbrellas 题目连接: http://codeforces.com/group/T0ITBvoeEx/contest/988/problem/E Description Polycarp lives on a coordinate line at the point x=0. He goes to his friend that lives at the point x=a. Polycarp can