P11299 [NOISG 2021 Finals] Fraud 题解
题目背景
你被任命为第 24 届全国信息学奥林匹克竞赛的负责人!
题目描述
本次竞赛共有 N 名参赛者和 2 轮比赛。第 i 名参赛者在第一轮获得了分,在第二轮获得了
分。
每轮比赛分别有一个正整数权重 X 和 Y。第 i 名参赛者的最终得分 计算公式为:
作为竞赛负责人,你可以自由选择 X 和 Y 的值。
然而,老鼠 Squeaky 贿赂了你,要求你选择某些 X 和 Y,使得 对所有 1≤i<j≤N 都成立。如果能做到,他会重金酬谢。
但是,这是否可能呢?
输入格式
- 第一行包含一个整数 N,表示参赛者的数量。
- 第二行包含 N 个整数 A1,A2,…,AN,表示第一轮的得分。
- 第三行包含 N 个整数 B1,B2,…,BN,表示第二轮的得分。
输出格式
输出一行:如果可以实现目标,输出 YES
;否则输出 NO
。
输入输出样例
输入 #1
2
1 2
2 1
输出 #1
YES
输入 #2
3
2 4 3
4 2 3
输出 #2
NO
输入 #3
2
5 1
0 0
输出 #3
YES
说明/提示
【样例解释】
- 对于样例 1,选择 X=1 和 Y=2,此时
=1×1+2×2=5,
=2×1+1×2=4,满足条件。
- 对于样例 2,无论如何选择 X 和 Y,都无法满足条件。
- 对于样例 3,选择任意非零 X 均满足条件,因为
。
【数据范围】
- 2 ≤ N ≤
- 0 ≤
≤
子任务编号 | 分值 | 额外限制条件 |
---|---|---|
1 | 10 | Bi=0 |
2 | 25 | N=2 |
3 | 50 | 2≤N≤ |
4 | 15 | 无额外限制 |
代码 :
#include <bits/stdc++.h>
#define int long long
using namespace std;const int MAXN = 3e5 + 5;
int n, a[MAXN], b[MAXN]; // 上界与下界struct frac {int zi, mu;
} mx, mn;frac make_frac(int a, int b) {if (b < 0) return (frac){-a, -b};else return (frac){a, b};
}frac maxx(frac a, frac b) {if (a.zi * b.mu - b.zi * a.mu < 0) return b;else return a;
}frac minn(frac a, frac b) {if (a.zi * b.mu - b.zi * a.mu < 0) return a;else return b;
}signed main() {cin >> n;for (int i = 1; i <= n; i++) {cin >> a[i];}for (int i = 1; i <= n; i++) {cin >> b[i];}mx = {1000000000, 1};mn = {-1000000000, 1};for (int i = 1; i < n; i++) {if (b[i + 1] > b[i]) {mx = minn(mx, make_frac(a[i + 1] - a[i], b[i] - b[i + 1]));} else if (b[i + 1] < b[i]) {mn = maxx(mn, make_frac(a[i + 1] - a[i], b[i] - b[i + 1]));} else if (a[i + 1] >= a[i]) {cout << "NO" << endl;return 0;}}if (mx.zi * mn.mu - mn.zi * mx.mu <= 0 || mx.zi <= 0) {cout << "NO" << endl;} else {cout << "YES" << endl;}return 0;
}
代码结构解析:
-
全局变量与结构体介绍:
-
MAXN
:数组最大长度。 -
a[], b[]
:分别存储上下界相关数据。 -
frac
结构体:表示分数,包含分子zi
和分母mu
。 -
make_frac
:创建分数并确保分母为正。 -
maxx
和minn
:比较两个分数,返回较大/较小值。
-
-
主函数逻辑:
-
输入处理:读取数组
a
和b
的值。 -
初始化上下界:
mx
(上界)初始化为极大正数,mn
(下界)初始化为极大负数。 -
遍历处理相邻元素:
-
当
b[i+1] > b[i]
:推导出x的上界,更新mx
为更小值。 -
当
b[i+1] < b[i]
:推导出x的下界,更新mn
为更大值。 -
当
b[i+1] == b[i]
:若a[i+1] ≥ a[i]
,直接输出"NO"(无法满足条件)。
-
-
最终判断:
-
若所有约束条件下,存在x使得
mn ≤ x ≤ mx
且mx > 0
,输出"YES";否则输出"NO"。
-
-
核心思路:
-
约束条件推导:对于每个相邻元素i和i+1,根据
b
的变化情况,推导x的上下界:-
b[i+1] > b[i]
:x需满足上界,取所有上界的最小值。 -
b[i+1] < b[i]
:x需满足下界,取所有下界的最大值。 -
b[i+1] == b[i]
:若a
不满足非递增,直接无解。
-
-
最终验证:检查上下界是否有效(下界≤上界且上界为正)。
示例分析:
假设输入为:
3
2 5 7
3 1 4
则:
代码会遍历相邻元素,计算x的约束,最终判断是否存在满足条件的正数x。若存在,输出"YES",否则"NO"。
总结:
通过分数运算和交叉相乘比较,高效处理了所有约束条件,确保在O(n)时间内完成判断。