做题记录整理贪心3 520. 「LibreOJ β Round #3」绯色 IOI(开端)(2022/9/13)
520. 「LibreOJ β Round #3」绯色 IOI(开端)
题目说的花里胡哨的,其实意思就是有n个数,把每个数都看成一个点,把所有点连成一个环,最后使
(a1-a2)^2 +(a2-a3)^2 +(a3-a4)^2 ...+(a n-1 - a n)^2 +(a n - a1)^2 最大
把这串式子拆开,会发现其实就是整个序列的权值平方和的两倍-相邻的点乘积的两倍,所以就转化成了把求相邻点的乘积最小化,自然就可以贪心了
#include <bits/stdc++.h>
using namespace std;
#define for1(i,a,b) for(ll i = a;i <=b;i++)
#define ll long long
struct node {
ll pf;
ll zhi;
int vis;
} a[500005];
int n, m;
bool cmp(node x, node y) {
return x.zhi > y.zhi;
}
ll ans;
int main() {
scanf("%d", &n);
for1(i, 1, n)
scanf("%lld", &a[i].zhi),
a[i].pf = a[i].zhi * a[i].zhi,
a[i].vis = 0;
sort(a + 1, a + n + 1, cmp);
if (n == 2) {
cout << a[1].pf * 2 + a[2].pf * 2 - 4 * a[1].zhi *a[2].zhi;
return 0;
}
for1(i, 1, n) {
int ji = 1;
if (i + ji > n)
break;
if (a[i + ji].vis == 0 || i + ji == n) {
a[i + ji].vis = 1;
ans += a[i + ji].zhi * a[i].zhi * 2;
}
ji++;
if (i + ji > n && n != 2)
break;
if (a[i + ji].vis == 0 || i + ji == n) {
a[i + ji].vis = 1;
ans += a[i + ji].zhi * a[i].zhi * 2;
}
}
ans *= -1 * 1ll;
for1(i, 1, n) {
ans += a[i].pf * 2;
}
cout << ans << endl;
return 0;
}

浙公网安备 33010602011771号