专栏文章
题解:P10730 [NOISG 2023 Qualification] Burgers
P10730题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @miq836r7
- 此快照首次捕获于
- 2025/12/04 00:29 3 个月前
- 此快照最后确认于
- 2025/12/04 00:29 3 个月前
Statement
为了避免歧义,这里用 分别指代两种糖数量,用 表示原文 。
可以认为是 , 求最大的 。
Sol
几何意义上这是求一个(二维)凸包内 最大的点,可以用一些很 fancy 的算法解决,但是都很难。考虑转化一下。
二分答案,假设 。思考下怎么验证。
可以通过消掉 的方式求出 的范围。
&a_ix + b_i y \le c_i \\
\Rightarrow & (a_i - b_i) x + b_i(x+y) \le c \\ \Rightarrow & (a_i - b_i) x \le c - b_i d \\
\end{aligned}
分类讨论 。不难得到
check 的时候只需要保证第二种情况得到满足,第一、三种解出来不是空集就可以。当然注意 是整数,第一种情况下商直接下取整,第二种上取整即可。
Code
CPP#include<iostream>
#include<algorithm>
#include<vector>
#include<numeric>
using namespace std;
int n, ans = 0;
vector<long long> a, b, c;
bool check(int d){ // if x + y = d has solution
long long maxx = d, minx = 0;
for(int i = 0; i < n && minx <= maxx; i++){
if(a[i] > b[i])
maxx = min(maxx, (c[i] - b[i] * d) / (a[i] - b[i]));
else if (a[i] < b[i])
minx = max(minx, (c[i] - b[i] * d -1) / (a[i] - b[i]) + 1);
else if (a[i] * d > c[i]) return false;
}
return minx <= maxx;
}
int main(){
ios::sync_with_stdio(0),
cin.tie(0), cout.tie(0);
cin >> n;
for(auto vec:{&c, &a, &b}){
vec->resize(n);
for(long long&vx:(*vec))
cin >> vx;
}
for(int k = (1<< 30); k; k>>=1){
if(ans + k < 1e9 && check(ans+k))
ans += k;
}
cout << ans << endl;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...