CF1851D
貌似我与大家后面的判断不太一样?
分析
由于前缀和的定义,我们可以知道他们的差分便是原数组,下面的差分数组,是题目给出的前缀和的差分。
于是,我们可以用个桶将 \(1 \sim N\) 出现的数存起来。
随后判断每个数是否出现过,若没出现过,使计数器加一。
这里我们假设输出 YES
。因为前缀和少了一个数,那么我们得到的差分数组则会比原数组少一个元素。如果 \(cnt = 2\),则差分数组相较于原数组会有一个不同的元素,而这一个元素便是原数组在差分数组中,没有出现的两个元素的和。如果 \(cnt = 1\),那么一定是前缀和的最后一个数加上差分数组缺少的那一个数等于 \(1 \sim N\) 之和。
这个时候我们分三种情况:
- 如果 \(cnt > 2\),我们根据定义可以得出是不可行的,直接输出
NO
。 - 如果 \(cnt = 2\),我们则需判断前缀和数组中最后一个元素是否是 \(1 \sim N\) 的和,若相等则输出
YES
,否则NO
。 - 如果 \(cnt = 1\),我们则判断前缀和的最后一个数加上差分数组缺少的那一个数是否等于 \(1 \sim N\) 之和。
Code
#include <bits/stdc++.h>
#define ll long long
#define vint vector<int>
#define ull unsigned ll
using namespace std;
const int N = 4e5 + 5;
ll t, n, c[N], pre, now;
int main() {
ios::sync_with_stdio(0);
cin >> t;
while (t--) {
pre = 0;
cin >> n;
// ll sum = 0;
memset(c, 0, sizeof c);
for (int i = 1; i < n; i++) {
cin >> now;
if (now - pre <= 4e5) c[now - pre]++;//标记数已经出现过
pre = now;
}
int cnt = 0, x[N] = {0};//x 数组保存差分数组缺少的数
for (int i = 1; i <= n; i++) {
if (!c[i]) {
cnt++;
x[cnt] = i;
}
}
if (cnt > 2) puts("NO");
else if (cnt == 1) {
if (x[1] + now == (1 + n) * n / 2) puts("YES");
else puts("NO");
}
else {
if (now != (1 + n) * n / 2) {
puts("NO");
continue;
}
else {
puts("YES");
}
}
}
return -1;
}