题解:CF1810D Climbing the Tree
· 阅读需 3 分钟
原题链接
解题思路
设当前可能的树高范围为 。
初 始时,树高可能为任意正整数,所以令 。
1. 事件
一只属性为 的蜗牛声称花了 天爬树。
设符合条件的树高范围为 。
前 天,白天上爬 米,晚上下滑 米,每天爬 米;最后 天最多爬 米。所以 米。
爬了 天意味着第 天没有爬到树顶,同理 天最多 爬 米。所以 米。
计算 和 的交集,如果为空,说明该信息有冲突,直接忽略;否则树高范围需要同时满足这两个集合,即将 设为两者的交集。
2. 事件
一只属性为 的蜗牛询问爬树所需天数。
当树高为 米时,设所需天数为 天。
最后 天爬 米,还剩 米;前面每天爬 米,需要 天。所以 天。
显然,当 时,所需天数最少;当 时,所需天数最多。如果两者相等,便可以得出精确的答案。
3. 注意事项
- 在事件 中,当 时,最小树高 米。
- 在事件 中,显然所需天数至少为 天。
- 使用
double
类型,可能会导致精度丢失。建议根据以下公式手写取上整函数:
参考代码
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
const ll inf=0x3f3f3f3f3f3f3f3f;
const int mod=1e9+7;
const int N=200005;
ll up(ll a,ll b){return (a+b-1)/b;}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin>>T;
while(T--)
{
ll L=1,R=inf;
int q;
cin>>q;
while(q--)
{
int op;
ll a,b,n;
cin>>op;
if(op==1)
{
cin>>a>>b>>n;
ll mn=(n==1?1:(a-b)*(n-2)+a+1);
ll mx=(a-b)*(n-1)+a;
if(mx<L||mn>R)
{
cout<<0<<' ';
}
else
{
cout<<1<<' ';
L=max(L,mn);
R=min(R,mx);
}
}
else
{
cin>>a>>b;
ll mn=max(up(L-a,a-b)+1,1ll);
ll mx=max(up(R-a,a-b)+1,1ll);
cout<<(mn==mx?mn:-1)<<' ';
}
}
cout<<'\n';
}
return 0;
}