[Codeforce刷题7]

A. 晚餐时间

https://codeforces.com/contest/2102/problem/A

每次测试的时间限制: 1 秒
每次测试的内存限制: 256 兆字节
输入: 标准输入
输出: 标准输出

给定四个整数 n n n m m m p p p q q q,判断是否存在满足以下条件的整数数组 a 1 , a 2 , … , a n a_1, a_2, \ldots, a_n a1,a2,,an(元素可能为负数):

  • 数组中所有元素的和等于 m m m: a 1 + a 2 + … + a n = m a_1 + a_2 + \ldots + a_n = m a1+a2++an=m
  • p p p 个连续元素之和等于 q q q: a i + a i + 1 + … + a i + p − 1 = q ,  for all  1 ≤ i ≤ n − p + 1 a_i + a_{i + 1} + \ldots + a_{i + p - 1} = q,\qquad\text{ for all }1\le i\le n-p+1 ai+ai+1++ai+p1=q, for all 1inp+1

输出

对于每个测试用例,如果存在满足上述条件的数组,则输出 “YES”(不带引号),否则输出 “NO”(不带引号)。

您可以在任何情况下输出 “YES” 和 “NO”(例如,字符串 “yES”、“yes” 和 “Yes” 都将被视为有效响应)。

解题思路

特殊情况处理
  • p = n p = n p=n:此时整个数组的和必须等于 q q q,因此只需检查 m m m 是否等于 q q q

  • p = 1 p = 1 p=1:每个元素必须等于 q q q,因此总和应为 n ⋅ q n \cdot q nq,检查 m m m 是否等于 n ⋅ q n \cdot q nq

  • n n n p p p 的倍数时:可以将数组分成 n / p n/p n/p 段,每段的和为 q q q,因此总和应为 q ⋅ ( n / p ) q \cdot (n/p) q(n/p),检查 m m m 是否等于 q ⋅ ( n / p ) q \cdot (n/p) q(n/p)

一般情况

如果上述特殊情况均不满足,则一定可以构造一个满足条件的数组。

AC Code
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

void solve(){
    ll n, m, p, q;
    cin >> n >> m >> p >> q;
    if (p == n) {
        cout << (m == q ? "YES" : "NO") << "\n";
        return;
    }
    if (p == 1) {
        cout << (m == n * q ? "YES" : "NO") << "\n";
        return;
    }
    if (n % p == 0) {
        cout << (m == q * (n / p) ? "YES" : "NO") << "\n";
        return;
    }
    cout << "YES" << "\n";
}

int main() {
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);

    int t;
    cin >> t;
    while (t--) {
        solve();
    }
    return 0;
}

B. 挑剔的猫

https://codeforces.com/contest/2102/problem/B

每次测试的时间限制: 1 秒钟
每次测试的内存限制: 256 兆字节
输入: 标准输入
输出: 标准输出

给你一个整数数组 a 1 , a 2 , … , a n a_1, a_2, \ldots, a_n a1,a2,,an。您可以执行以下操作任意多次(可能为零):

  • 选择一个索引 i i i ( 1 ≤ i ≤ n 1 \le i \le n 1in)。将 a i a_i ai 乘以 − 1 -1 1 (即更新 a i : = − a i a_i := -a_i ai:=ai)。

你的任务是判断是否有可能在进行任意次数的上述操作后,使位于索引 1 1 1 的元素成为数组的中位数。请注意,操作也可以应用于索引 1 1 1 中,这意味着中值可以是 a 1 a_1 a1 的原始值,也可以是其否定值。

数组 b 1 , b 2 , … , b m b_1, b_2, \ldots, b_m b1,b2,,bm 的中值定义为数组 b b b ⌈ m 2 ⌉ \left\lceil \frac{m}{2} \right\rceil 2m-th ∗ ^{\text{∗}} 最小的元素。例如,数组 [ 3 , 1 , 2 ] [3, 1, 2] [3,1,2] 的中位数是 2 2 2,而数组 [ 10 , 1 , 8 , 3 ] [10, 1, 8, 3] [10,1,8,3] 的中位数是 3 3 3

可以保证 a a a 中元素的绝对值是不同的。从形式上看,没有一对索引 1 ≤ i < j ≤ n 1 \le i < j \le n 1i<jn ∣ a i ∣ = ∣ a j ∣ |a_i| = |a_j| ai=aj 中。

∗ ^{\text{∗}} ⌈ x ⌉ \lceil x \rceil x 是向上取整函数,返回大于或等于 x x x 的最小整数。

输入

每个测试包含多个测试用例。第一行包含测试用例的数量 t t t ( 1 ≤ t ≤ 1 0 4 1 \le t \le 10^4 1t104)。测试用例说明如下。

每个测试用例的第一行包含一个整数 n n n ( 1 ≤ n ≤ 1 0 5 1 \le n \le 10^5 1n105) - 数组的长度 a a a

每个测试用例的第二行包含 n n n 个整数 a 1 , a 2 , … , a n a_1, a_2, \ldots, a_n a1,a2,,an ( ∣ a i ∣ ≤ 1 0 6 |a_i| \le 10^6 ai106, ∣ a i ∣ ≠ ∣ a j ∣ |a_i| \neq |a_j| ai=aj) - 数组 a a a 的元素。

保证所有测试用例中 n n n 的总和不超过 1 0 5 10^5 105

输出

对于每个测试用例,如果可以使索引 1 1 1 处的元素成为数组的中位数,则输出 “是”,否则输出 “否”。

您可以输出任何大小写的答案(大写或小写)。例如,字符串 “yEs”、“yes”、"Yes "和 "YES "将被识别为肯定回答。

方法思路

问题分析:

数组的中位数是第 ⌈ n / 2 ⌉ \lceil n/2 \rceil n/2 小的元素。

我们可以调整任意元素的符号,因此需要考虑两种情况:第一个元素为正或负。

关键观察:

  1. 如果第一个元素的绝对值是 A A A,那么其他元素可以分为两部分:绝对值小于 A A A 的元素和绝对值大于 A A A 的元素。
  2. 当保持第一个元素为正时,所有绝对值小于 A A A 的元素在处理后的值都会小于 A A A,而绝对值大于 A A A 的元素可以通过符号调整使其值小于或大于 A A A
  3. 当将第一个元素取反时,所有绝对值小于 A A A 的元素在处理后的值都会大于 − A -A A,而绝对值大于 A A A 的元素可以通过符号调整使其值小于或大于 − A -A A

条件判断:

  1. 保持第一个元素为正时,需要保证绝对值小于 A A A 的元素数量加上部分绝对值大于 A A A 的元素数量足够使其成为中位数。
  2. 将第一个元素取反时,需要保证绝对值大于 A A A 的元素数量足够使其成为中位数。

结果

  1. n=1,直接输出YES
  2. n>1,当绝对值比 n u m [ 1 ] num[1] num[1]小的个数smaller_count < (n+1)/2或者绝对值比 n u m [ 1 ] num[1] num[1]大的个数larger_count > (n+1)/2满足条件,输出YES;否则不满足,输出NO
AC Code
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
  
void solve() {
    int n;
    cin >> n;
    if (n == 1) {
        int x;
        cin >> x;
        cout << "YES\n";
        return;
    }

    int first;
    cin >> first;
    int first_abs = abs(first);
    int smaller_count = 0;
    int larger_count = 0;
    for (int i = 1; i < n; i++) {
        int x;
        cin >> x;
        int abs_x = abs(x);
        if (abs_x < first_abs) {
            smaller_count++;
        } else if (abs_x > first_abs) {
            larger_count++;
        }
    }
    int target_pos = (n + 1) / 2;
    int required = target_pos - 1;
    if (smaller_count <= required || larger_count >= required) {
        cout << "YES\n";
    } else {
        cout << "NO\n";
    }
}

int main() {
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Almond_s

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值