My Solution
题意:每个萝卜长度为 hi = a + (i - 1) * b,然后每次询问是每次操作最多把 m 个不同的未吃完的萝卜每个咬掉1单位长度,最多 t 次操作,其中求最大的r,是的[l......r]访问内的萝卜被这 t,m的操作吃完
二分搜索+数列
首先r必须且只要满足2个条件即可,1)a + (r - 1) * b <= t
2) sum{hi | l <= i <= r } <= t * m
所以对于每个询问进行一次二分搜索即可。
suml = (2 * a + ((l - 1) - 1) * b) * (l - 1) / 2;
LL x = l, y = (t - a) / b + 1 + 1, mid; // y = (t - a) / b + 1 + 1 多加个1不上整数除法的精度损失, 也可以直接用y = 2e6
while(x + 1 < y){
mid = (x + y) >> 1;
if(check(a, b, suml, t, m, mid)) x = mid;
else y = mid;
}
然后答案可能在x里也可能在y里,且y比x更优,所以
if(check(a, b, suml, t, m, y)) r = y;
else if(check(a, b, suml, t, m, x)) r = x;
else r = -1;
即可
复杂度 O(nlogn)
#include
#include
#include
using namespace std;
typedef long long LL;
const int maxn = 1e6 + 8;
inline bool check(const LL &a, const LL &b, LL &suml, const LL &t, const LL &m, const LL &mid)
{
if(a + (mid - 1) * b > t) return false;
if((2*a + (mid - 1) * b) * mid / 2 - suml > t * m) return false;
else return true;
}
int main()
{
#ifdef LOCAL
freopen("c.txt", "r", stdin);
//freopen("c.out", "w", stdout);
int T = 2;
while(T--){
#endif // LOCAL
ios::sync_with_stdio(false); cin.tie(0);
LL a, b, n, l, t, m, r, suml;
cin >> a >> b >> n;
while(n--){
r = -1;
cin >> l >> t >> m;
suml = (2 * a + ((l - 1) - 1) * b) * (l - 1) / 2;
LL x = l, y = (t - a) / b + 1 + 1, mid; // y = (t - a) / b + 1 + 1 多加个1不上整数除法的精度损失, 也可以直接用y = 2e6
while(x + 1 < y){ mid = (x + y) >> 1;
if(check(a, b, suml, t, m, mid)) x = mid;
else y = mid;
}
//cout << x << " " << y << endl;
if(check(a, b, suml, t, m, y)) r = y;
else if(check(a, b, suml, t, m, x)) r = x;
else r = -1;
if(n) cout << r << "n";
else cout << r << endl;
}
#ifdef LOCAL
cout << endl;
}
#endif // LOCAL
return 0;
}
非特殊说明,本博所有文章均为博主原创,未经许可不得转载。
https://www.prolightsfxjh.com/
Thank you!
------from ProLightsfx
非特殊说明,本博所有文章均为博主原创,未经许可不得转载。
如经许可后转载,请注明出处:https://prolightsfxjh.com/article/codeforces-round-299-div-2-c-tavas-and-karafs/
共有 0 条评论