序列操作
问题描述
存在一个序列 a, 是否存在一个数 K, 使得一些数加上 K,一些数减去 K,一些数不变,使得整个序列中所有的数相等。 其中对于序列中的每个位置上的数字,至多只能执行一次加运算或减运算或是对该位置不进行任何操作。
|
输⼊第一行是一个正整数 t 表示数据组数。 接下来对于每组数据,输入的第一个正整数 n 表示序列 a 的长度,随后一行有 n 个整数,标号序列 a 。
|
Output
输出共包含 t 行,每组数据输出一行。对于每组数据,如果存在这样的 K,输出"YES",否则输出"NO"。(输出不包含引号)
|
Sample
Input: 2 5 1 2 3 4 5 5 1 2 3 4 5
Output: NO NO
|
数据范围
数据点(上限) |
t |
n |
ai |
1, 2 |
10 |
10 |
10 |
3, 4, 5 |
10 |
103 |
109 |
6, 7, 8, 9, 10 |
10 |
104 |
1015 |
Limitation
Time limit 1000 ms Memory limit 65536 kb
|
解题思路
操作只有,一些数加上k,一些数减去k,一些数不变,对于每一个数列,k恒定为一个数k或者其相反数。
可以把原数组排序,前面的数(小的数)加上k,中间的数不变,后面的数(大的数)减去k,所以一个数列中最多存在3个数:x - k, x, x + k,因此可以记录数列中有多少种不同的数。
如果不同的数种类 > 3,则不存在k;
若种类 = 1 或 2,则一定存在k;
若种类 = 3,则可以记录不同数出现的位置,记下这3个不同数:若(小的数+大的数)=2×中间的数
,则一定存在k,否则k不存在。
模拟的时候,没有注意数据范围,用的int
,后面几组数据WA
了,后来改成long long
就过了……所以一定要留意数据范围啊!
源代码
#include <iostream> #include <algorithm> using namespace std;
bool solve(long long* a, int n) { sort(a, a + n); int count = 0; int dif[10]; for (int i = 1; i < n; i++) { if (a[i] != a[i - 1]) { dif[count] = i; count++; } if (count > 2) { return false; break; } } if (count == 2) { long long x = a[dif[0] - 1]; long long y = a[dif[0]]; long long z = a[dif[1]]; if (x + z != 2 * y) return false; else return true; } if (count == 1 || count == 0) return true; }
int main() { int t; cin >> t; for (int ii = 0; ii != t; ii++) { int n; cin >> n; long long* a = new long long[n + 10]; for (int i = 0; i < n; i++) cin >> a[i]; bool ans = solve(a, n); if (ans) cout << "YES" << endl; else cout << "NO" << endl; } return 0; }
|