题目大意:
给定区间 [ L , R ] [L,R] [L,R]问一个最小的 n n n使得区间 [ L , R ] [L,R] [L,R]存在于一棵根节点为 [ 0 , n ] [0, n] [0,n]的线段树中
解题思路:
可以发现 [L, R] 的父节点代表的区间至多有 4 种,分别为 [ L , 2 R − L ] , [ L , 2 R − L + 1 ] , [ 2 L − R − 2 , R ] , [ 2 L − R − 1 , R ] , [L, 2R−L], [L, 2R−L+ 1], [2L− R − 2, R], [2L − R − 1, R], [L,2R−L],[L,2R−L+1],[2L−R−2,R],[2L−R−1,R],只需要暴力枚举这些搜下去就好了,当两端超出限制的时候退出。
A c c e p t e d c o d e : Accepted\ code: Accepted code:
#include<cstdio>
#include<iostream>
#define int long long
const int N = 1e17;
int ans, L, R, lim, T;
void dfs(int l, int r) {
if (r > lim || r >= ans) return;
if (l == 0) { ans = r; return; }
int cnt = r - l + 1;
if (l - cnt == 0 || l - cnt >= cnt + cnt) dfs(l - cnt, r);
if (l - cnt == 1 || l - cnt - 1 >= cnt + cnt + 1) dfs(l - cnt - 1, r);
if (l >= cnt + cnt - 1) dfs(l, r + cnt - 1);
if (l > cnt + cnt) dfs(l, r + cnt);
}
inline int read() {
int f = 0; char c = getchar();
while (!isdigit(c)) c = getchar();
while (isdigit(c)) f = f * 10 + c - 48, c = getchar();
return f;
}
signed main() {
T = read();
while (T--) {
L = read(); R = read(); lim = read();
ans = N; dfs(L, R);
if (ans == N) printf("-1\n");
else printf("%d\n", ans);
}