Codeforces Round #608 (Div. 2) E - Common Number (二分 思维)

🥟 🥟 🥟
题意:
在这里插入图片描述首先我们可以按照题意把 1 ~ n 的路径画一下,比如这里取 n = 14 ,就可以得到下面这个可爱的树🌲
丑就丑吧实在没办法WA

从这个树可以得出几个结论:
1.数值x在1~n中出现的次数等于以他为根节点的树的大小
2.子树大小分奇偶有序,如:1 > 3 > 5 > 7,但 3与4大小不确定,所以必须分奇偶二分;
3.为了方便计算某节点为根的子树大小,我们规定奇数为左子树,偶数为右子树,由图可以看出一个树可以分成若干条链,链与链之间是(l2,r2+1)的关系,例如以2为根节点,可以分成【2,3】—>【4,7】—>【8,14】(这里应该是【8,15】但是n限制在了14),奇数为根节点类似。
代码如下:

ll n,k;
bool ok(ll x)
{
    queue<pair<ll,ll>>q;
    if(x&1) q.push(make_pair(x,x));
    else q.push(make_pair(x,x+1));
    ll ans=0;
    while(q.size())
    {
        auto it=q.front();q.pop();
        ans+=min(n,it.second)-it.first+1;
        if((it.first<<1)<=n) q.push(make_pair(it.first<<1,it.second<<1|1));
    }
    return ans>=k;
}
int main()
{
    cin>>n>>k;
    ll ans=0;
    {
        ll l=0,r=n/2,res=0;
        while(l<=r)
        {
            ll mid=(l+r)>>1;
            if(ok(mid<<1|1)) l=mid+1,res=mid<<1|1;
            else r=mid-1;
        }
        ans=max(ans,res);
    }
    {
        ll l=1, r=n/2, res=0;
        while(l<=r) 
        {
            ll mid = (l+r)>>1;
            if(ok(mid<<1))  l = mid+1, res=mid<<1;
            else    r = mid-1;
        }
        ans = max(ans, res);
    }
    cout<<ans<<endl;
    //stop;
    return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值