题目:点击打开链接
给一对数[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;
}
}