CF538E Demiurges Play Again题解

 题意


$n \le 2 \times 10^5$的一棵树,两个人轮流玩树上向下走一步,一个人先手,先手最大化收益,后手最小化收益,收益为最终到的叶子的权值,问当先手分配叶子权值(为一个排列)最大化收益为多少,后手最小化收益为多少。


分析


注意到相对大小与单调性,我们尝试二分验证$mid$是否是对于先手而言可以分配取到的收益。

此时我们把过程描述为,至少需要放多少个$1$在叶子,才能使得这个子树向下走可以必定走到一个 $1$的叶子。


代码

#include<bits/stdc++.h>
#define ll long long
#define dd double
using namespace std;
char gc()
{
    static char buf[1<<16],*s,*t;
    if(s==t)
    {
        t=(s=buf)+fread(buf,1,1<<16,stdin);
        if(s==t)return EOF;
    }
    return *s++;
}
ll read()
{
    char c;
    ll w=1;
    while((c=getchar())>'9'||c<'0')if(c=='-')w=-1;
    ll ans=c-'0';
    while((c=getchar())>='0'&&c<='9')ans=(ans<<1)+(ans<<3)+c-'0';
    return ans*w;
}
void pc(char c,int op)
{
    static char buf[1<<16],*s=buf,*t=buf+(1<<16);
    (op||((*s++=c)&&s==t))&&(fwrite(buf,1,s-buf,stdout),s=buf);
}
void wt(int x)
{
    if(x>9)wt(x/10);
    pc('0'+x%10,0);
}
void wts(int x,char op)
{
    if(x<0)
    {
        pc('-',0);
        x=-x;
    }
    wt(x);
    pc(op,0);
}
const int xx=2e5+5;
struct node
{
    int next,to;
}e[xx<<1];
int cnt,h[xx];
void add(int x,int y)
{
    cnt++;
    e[cnt].next=h[x];
    h[x]=cnt;
    e[cnt].to=y;
}
int n,num,cr[xx];
void gnum(int x,int y)
{
    int vs=1;
    for(int i=h[x];i;i=e[i].next)
    {
        if(e[i].to==y)continue;
        gnum(e[i].to,x);
        vs=0;
    }
    num+=vs;
    cr[x]=vs;
}
int f[xx];
void dp(int x,int y,int dep)
{
    if(cr[x])return f[x]=1,void();
    int mn=1e9,sum=0;
    for(int i=h[x];i;i=e[i].next)
    {
        if(e[i].to==y)continue;
        dp(e[i].to,x,dep^1);
        sum+=f[e[i].to];
        mn=min(mn,f[e[i].to]);
    }
    if(dep&1)f[x]=mn;
    else f[x]=sum;
}
bool check1(int mid)
{
    dp(1,0,1);
    return f[1]<=n-mid+1;
}
bool check2(int mid)
{
    dp(1,0,0);
    return f[1]<=mid;
}
signed main(){
    n=read();
    for(int i=1;i<n;i++)
    {
        int a=read(),b=read();
        add(a,b),add(b,a);
    }
    gnum(1,0);
    dp(1,0,1);
    cout<<num+1-f[1]<<" ";
    dp(1,0,0);
    cout<<f[1]<<endl;
    pc('1',1);
    return 0;
}


 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值