hdu 5323 Solve this interesting problem

题目:点击打开链接


给一对数[l,r],问找出最小的n使得线段树的根节点的左右范围是[0,n],且该线段树中有左右范围为[l,r]的节点 由于l/(r-l+1)≤2015,可以直接暴力搜索以[l,r]为节点的其父亲节点的情况,然后比较其最小值


搜索,线段树区间的分配方法决定了向上反推的时候可能有四种情况,这样就要向四个方向搜索分别是

[l,r+len]     [l,r+len-1]      [l-len,r]       [l-len-1,r]

是因为区间长度的奇偶性造成的。

重要的剪枝是如果L已经小于0,或者已经大于length,那么则不可能是通过任何一个区间分出来的。那么停止搜索,其他的每次搜索到l==0的时候表示找 到了一个新的满足要求的区间,则进行一次更新。第二个剪枝是如果r已经大于了现有的n。那么则再怎么搜索下去也不可能得到更小的.

 

代码:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>

using namespace std;
typedef long long ll;

const ll inf = 1e18;
ll ans;
void dfs(ll L, ll R)
{
        if (R>=ans) 
            return;
        if (L<0) 
            return;
        if(L==0) 
        {
            ans=R;
            return;
        }
        if (R-L+1>L) 
            return;
        dfs(2*L-R-1,R);
        dfs(2*L-R-2,R);
        dfs(L,2*R-L);
        dfs(L,2*R-L+1);
}
ll L, R;
int main()
{
        while(cin>>L>>R)
        {
            ans=inf;
            dfs(L,R);
            if(ans==inf) 
                ans= -1;
            cout<<ans<<endl;
        }
}




害羞

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值