Codeforces 898E Squares and not squares

链接

传送门

题意

给出\(n\)个数,\(n\)为偶数,每次操作可以选择一个数字加1或者减1,要求将这\(n\)个数分成两组,一组都是平方数,另一组都不是平方数。

思路

对于平方数,变为非平方数0需要2步,其他的需要1步。对于非平方数,可以预处理所有平方数,然后二分找到最接近的求解。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>

typedef long long LL;

using namespace std;

const int maxn = 200010;
const int maxm = 31625;

int sqnum[maxm];

vector<int> sq, nsq;

int main() {
for (int i = 0; i < maxm; ++i) {
sqnum[i] = i * i;
}
int n;
scanf("%d", &n);
for (int i = 0, x; i < n; ++i) {
scanf("%d", &x);
int *it = lower_bound(sqnum, sqnum + maxm, x);
if (*it == x) {
sq.push_back(x == 0 ? 2 : 1);
} else {
nsq.push_back(min(*it - x, x - *(it - 1)));
}
}
n /= 2;
LL ans = 0;
if (sq.size() > nsq.size()) {
int dt = n - int(nsq.size());
sort(sq.begin(), sq.end());
for (int i = 0; i < dt; ++i) {
ans += sq[i];
}
} else {
int dt = n - int(sq.size());
sort(nsq.begin(), nsq.end());
for (int i = 0; i < dt; ++i) {
ans += nsq[i];
}
}
printf("%lld\n", ans);
return 0;
}