Codeforces Round #681 (Div. 1) A. Extreme Subtraction
Extreme Subtraction
题意#
你有一个序列 ,你可以进行 种操作:
- 选择前 个数,将它们全部减
- 选择后 个数,将它们全部减
由你自己定,并且每次操作可以不同。
问是否可以把通过若干次操作整个序列变为全是 的序列
本题多测,有 组数据
,,
样例 #1#
样例输入 #1#
4
3
1 2 1
5
11 7 9 6 8
5
1 3 1 3 1
4
5 2 1 10
样例输出 #1#
YES
YES
NO
YES
SOLUTION 1#
分析#
两种操作都为区间操作,并且目标结果为让所有的数字都为 ,那么可以对原数组的差分数组进行考虑,判断是否可以使所有的数字都相等即可,即让 。第一种操作在差分数组中的含义即 a[1] --, a[i] ++
,第二种操作在差分数组中的含义即 a[i] ++, a[n + 1] --
。如果最终可以让,那么差分数组中所有的负数相加的绝对值一定是小于等于 a[1]
的。
代码#
点击查看代码
#include<stdio.h>
const int N = 3E4 + 10;
int T, n, a[N];
int main() {
scanf("%d", &T);
while (T -- ) {
scanf("%d", &n);
for (int i = 1; i <= n; i ++ ) scanf("%d", a + i);
long long now = 0;
for (int i = 2; i <= n; i ++ ) if (a[i] - a[i - 1] < 0) {
now -= (a[i] - a[i - 1]);
}
puts(now <= a[1] ? "YES" : "NO");
}
return 0;
}
SOLUTION2#
分析#
题意可以转化为 构造一个单调不减的数组 inc 和 一个单调不增的数组 dec,使得 a[i] = inc[i] + dec[i]
,那么我们可以贪心的构造,inc[1] = 0, dec[1] = a[1]
,考虑inc[2]
和 dec[2]
:
dec[2] <= dec[1]
dec[2] + inc[2] = a[2]
,得出dec[2] <= a[2]
inc[2] >= inc[1]
, 得出dec[2] <= a[2] - inc[1]
要贪心的让 dec[2]
尽可能的大,因此取 dec[2] = min(dec[1], a[2] - inc[1])
,最后判断此时是否有解即可。
代码#
点击查看代码
#include <cstdio>
#include <algorithm>
template < typename T > inline void chkmax(T &x, T y) {x = x >= y ? x : y;}
template < typename T > inline void chkmin(T &x, T y) {x = x <= y ? x : y;}
template < typename T > inline T max(T x, T y) {return x >= y ? x : y;}
template < typename T > inline T min(T x, T y) {return x <= y ? x : y;}
constexpr int N = 3E4 + 10;
int n, a[N];
int inc[N];
int dec[N];
void solve2() {
scanf("%d", &n); //pre[0] = suf[n + 1] = 1E9;
for (int i = 1; i <= n; i ++ ) {
scanf("%d", a + i);
}
inc[1] = 0, dec[1] = a[1];
for (int i = 2; i <= n; i ++ ) {
dec[i] = min(dec[i - 1], a[i] - inc[i - 1]);
inc[i] = a[i] - dec[i];
if (inc[i] < inc[i - 1] || dec[i] > dec[i - 1] || inc[i] < 0 || dec[i] < 0) {
return puts("NO"), void();
}
}
puts("YES");
/*
如果执行将 [1, k] 的数字减去 1 这个操作,那么 a_i 执行的此时一定大于等于 a_{i+1}
因此原题可以转化为 构造一个单调不减的数组inc 和 一个单调不增的数组dec
使得 a[i] = inc[i] + dec[i]
贪心的构造,inc[1] = 0, dec[1] = a[1]
考虑inc[2] 和 dec[2]
dec[2] <= dec[1]
dec[2] + inc[2] = a[2] --> dec[2] <= a[2]
inc[2] >= inc[1] --> dec[2] <= a[2] - inc[1]
贪心的让dec[2] 尽可能的大,因此取 dec[2] = min(dec[1], a[2] - inc[1])
判断此时是否有解即可
*/
}
int main() {
int T; scanf("%d", &T);
while (T -- ) solve2();
return 0;
}
SOLUTION3#
分析#
考虑每个位置 ,如果 ,那么 这个位置至少要执行 次第一种操作,此时要考虑前缀最小值是否可以执行这么多次这个操作。 如果 ,那么 这个位置至少要执行 次第二种操作,此时要考虑后缀最小值是否可以执行这么多次这个操作。
如果都满足,则可以将整个序列变为全 序列。
代码#
点击查看代码
#include <bits/stdc++.h>
using namespace std;
template < typename T > inline void chkmax(T &x, T y) {x = x >= y ? x : y;}
template < typename T > inline void chkmin(T &x, T y) {x = x <= y ? x : y;}
constexpr int N = 3E4 + 10;
int n, a[N];
// int pre[N], suf[N];
void solve() {
scanf("%d", &n); //pre[0] = suf[n + 1] = 1E9;
for (int i = 1; i <= n; i ++ ) {
scanf("%d", a + i);
}
int mi = 1E9;
for (int i = 1; i < n; i ++ ) {
if (a[i] > a[i + 1] && mi < a[i] - a[i + 1]) {
return puts("NO"), void();
}
chkmin(mi, a[i]);
mi -= max(0, a[i] - a[i + 1]);
}
reverse(a + 1, a + 1 + n);
mi = 1E9;
for (int i = 1; i < n; i ++ ) {
if (a[i] > a[i + 1] && mi < a[i] - a[i + 1]) {
return puts("NO"), void();
}
chkmin(mi, a[i]);
mi -= max(0, a[i] - a[i + 1]);
}
puts("YES");
}
int main() {
int T; scanf("%d", &T);
while (T -- ) solve();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现