P11299 [NOISG 2021 Finals] Fraud 题解

题目背景

你被任命为第 24 届全国信息学奥林匹克竞赛的负责人!

题目描述

本次竞赛共有 N 名参赛者和 2 轮比赛。第 i 名参赛者在第一轮获得了A_i分,在第二轮获得了 B_i 分。

每轮比赛分别有一个正整数权重 X 和 Y。第 i 名参赛者的最终得分S_i​ 计算公式为:

S_i = A_i \times X + B_i \times Y

作为竞赛负责人,你可以自由选择 X 和 Y 的值。

然而,老鼠 Squeaky 贿赂了你,要求你选择某些 X 和 Y,使得 S_i>S_j 对所有 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,此时 S_1=1×1+2×2=5,S_2​=2×1+1×2=4,满足条件。
  • 对于样例 2,无论如何选择 X 和 Y,都无法满足条件。
  • 对于样例 3,选择任意非零 X 均满足条件,因为 S_ 1>S_2​。

【数据范围】

  • 2 ≤ N ≤ 3 \times 10^5
  • 0 ≤ A_i,B_i ≤ 10^6
子任务编号分值额外限制条件
110Bi​=0
225N=2
3502≤N≤10^4
415无额外限制

代码 :

#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;
}

代码结构解析:

  1. 全局变量与结构体介绍

    • MAXN:数组最大长度。

    • a[], b[]:分别存储上下界相关数据。

    • frac结构体:表示分数,包含分子zi和分母mu

    • make_frac:创建分数并确保分母为正。

    • maxxminn:比较两个分数,返回较大/较小值。

  2. 主函数逻辑

    • 输入处理:读取数组ab的值。

    • 初始化上下界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)时间内完成判断。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值