P11299 [NOISG 2021 Finals] Fraud
黄题,但是还是有思维难度的。
首先注意到我们只需要保证所有位置都比左边一位小就能够保证递减了,应该是显然的。
所以可以想到按位处理,只需要考虑每一位比它的后一位要大即可。
考虑需要满足什么条件。
首先如果 \(a_i\ge a_{i+1}\) 且 \(b_i\ge b_{i+1}\) 那就必定无解,因为 \(X\) 和 \(Y\) 全部都是正整数。
对于剩下的 \(a_i\le a_{i+1}\) 且 \(b_i\le b_{i+1}\) 的情况就必定成立了,也不需要再考虑。
讨论剩下的情况,如果 \(a_i<a_{i+1}\) 且 \(b_i>b_{i+1}\)。
需要满足 \(Xa_i+Yb_{i}>Xa_{i+1}+Yb_{i+1}\) 这一条件。
假设我们已经确定了 \(X\) 的值。
那么 \(Y\) 的范围可以确定为 \(Y>\frac{X(a_{i+1}-a_i)}{b_i-b_{i+1}}\)。
同理,在 \(a_i>a_{i+1}\) 且 \(b_i<b_{i+1}\) 时,范围为 \(Y<\frac{X(a_{i}-a_{i+1})}{b_{i+1}-b_{i}}\)。
那么就可以确定一个大概的范围,只要下界小于上界,\(X\) 取一个非常大的值,中间必定能够包含一个 \(Y\),就可以判断了。
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,a[300005],b[300005];
signed main(){
freopen("frd.in","r",stdin);
freopen("frd.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++)cin>>b[i];
double ma=0,mi=1e18;
for(int i=1;i<n;i++){
if(a[i]<=a[i+1]&&b[i]<=b[i+1]){
cout<<"NO";
return 0;
}
if(a[i]>=a[i+1]&&b[i]>=b[i+1])continue;
if(a[i]>=a[i+1]){
double tmp=1.0*(a[i]-a[i+1])/(b[i+1]-b[i]);
mi=min(mi,tmp);
}
else {
double tmp=1.0*(a[i+1]-a[i])/(b[i]-b[i+1]);
ma=max(ma,tmp);
}
}
if(ma<mi)cout<<"YES";
else cout<<"NO";
return 0;
}

浙公网安备 33010602011771号