题目链接:
题目大意:
给出一个区间,问存在以这个区间为左右区间的节点的最小的线段树。
题目分析:
首先对于线段树的一个节点,假设它的区间是[l,r],那么它的父亲的区间可能是
[L,2*R-L+1] , [L,2*R-L] , [2*L-2-R,R] , [2*L-R-1,R]
那么暴力求解即可。
那么暴力求解的复杂度是什么呢?
首先因为L/区间长度<=2015,所以最多向上翻2^11倍,每次再一直找左区间,又是一个最坏2^11的复杂度,所以最坏复杂度O(2^11)
所以暴力求解是可以的。
代码如下:
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
const LL INF = 1e18+7;
LL ans = INF;
LL l,r;
void dfs ( LL l , LL r )
{
if ( r >= ans ) return;
if ( l < 0 || r < l ) return;
if ( l == 0 )
{
ans = min ( ans , r );
return;
}
if ( r - l + 1 > l ) return;
dfs ( l , (r<<1)-l+1 );
dfs ( l , (r<<1)-l );
dfs ( (l<<1)-2-r , r );
dfs ( (l<<1)-r-1 , r );
}
int main ( )
{
while (~scanf ( "%I64d%I64d" , &l , &r ))
{
ans = INF;
if ( l == r || l == 0 ) ans = r;
else dfs ( l , r );
if ( ans != INF )
printf ("%I64d\n" , ans );
else puts ( "-1" );
}
}