做题记录整理贪心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;
}
posted @ 2022-09-13 16:29  yyx525jia  阅读(108)  评论(0)    收藏  举报