1962. Climbing the Tree

(a,b,n) 可以确定唯一的可能高度区间 [a(n-1)-b(n-2)+1,an-b(n-1)] (特判 n=1[1,a])。对每个新的 (a,b,n),如果与原有的区间不相交,不合法,否则,取重复区间。

对询问 (a,b),设已知高度为 h,则最少需要 an-b(n-1)\ge h 天,解得 n=\lceil\dfrac{h-b}{a-b}\rceil,特判 h\le a1 天。对区间两个端点分别计算出 n,如果 n 一致,输出,否则说不知道。

单次操作复杂度 O(1)

#include <bits/stdc++.h> using namespace std; using ll = long long; using pr = pair<ll, ll>; const ll inf = 5e18; bool intersect(pr x, pr y) { return !(x.second < y.first || y.second < x.first); } pr combine(pr x, pr y) { return {max(x.first, y.first), min(x.second, y.second)}; } ll cei(ll a, ll b) { return (a + b - 1) / b; } pr rng(ll a, ll b, ll n) { if (n == 1) { return {1, a}; } return {a * (n - 1) - b * (n - 2) + 1, a * n - b * (n - 1)}; } ll minday(ll a, ll b, ll h) { if (h <= a) { return 1; } return cei(h - b, a - b); } signed main() { ios::sync_with_stdio(false), cin.tie(0); ll t; cin >> t; while (t--) { pr eff = {0, inf}; ll q; cin >> q; while (q--) { ll cmd, a, b, n; cin >> cmd >> a >> b; if (cmd == 1) { cin >> n; pr nw = rng(a, b, n); if (intersect(eff, nw)) { cout << "1 "; eff = combine(eff, nw); } else { cout << "0 "; } } else { ll l = minday(a, b, eff.first); ll r = minday(a, b, eff.second); if (l == r) { cout << l << ' '; } else { cout << "-1 "; } } } cout << "\n"; } return 0; }