对 (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 a 为 1 天。对区间两个端点分别计算出 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;
}