题意
构建一棵线段树的函数为build(1,0,n)build(1,0,n)build(1,0,n)。
给出ttt个询问,求出区间[l,r][l,r][l,r]能在这棵树中出现的最小的nnn。
思路
从下往上搜上去,区间[l,r][l,r][l,r]可能由四种情况传下来。
[l,2r−l][l,2r-l][l,2r−l]
[l,2r−l+1][l,2r−l+1][l,2r−l+1]
[2l−r−2,r][2l−r−2,r][2l−r−2,r]
[2l−r−1,r][2l−r−1,r][2l−r−1,r]
加点剪枝优化就可以过了。
代码
#include<cstdio>
#include<algorithm>
long long t, a, b, lim, ans;
long long input() {
char c = getchar();
int f = 1;
long long result = 0;
while (c < '0' || c > '9') {
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') {
result = result * 10 + (c - 48);
c = getchar();
}
return result * f;
}
void write(long long x) {
if (x > 9) write(x / 10);
putchar(x % 10 + 48);
}
void print(long long x) {
if (x < 0) printf("-"), x *= -1;
write(x);
}
void println(long long x) {
print(x);
putchar(10);
}
void dfs(long long l, long long r) {
if (l == 0) {
ans = std::min(ans, r);
return;
}
if (r >= ans || 2 * l < r) return;
if (l < 2 * r - l) dfs(l, 2 * r - l);
if (l < 2 * r - l + 1) dfs(l, 2 * r - l + 1);
if (2 * l - 2 - r < r) dfs(2 * l - 2 - r, r);
if (2 * l - 1 - r < r) dfs(2 * l - 1 - r, r);
}
int main() {
t = input();
while (t--) {
long long f = 0;
a = input();
b = input();
lim = input();
ans = 2e9;
dfs(a, b);
if (ans == 2e9 || ans > lim) println(-1);
else println(ans);
}
}