CF1614B Divan and a New Project

题目大意

在一条街上,盖 n+1n+1 栋楼,每栋楼坐标为 xix_i,满足 ji,xixj\forall j \ne i,x_i \ne x_jxix_i 是一个整数。

将所有楼从 00nn 标号。

有一人在编号为 00 的楼,分别要去编号为 ii 的建筑 aia_i 次,这个人往返编号为 ii 的建筑一趟花费的时间为 2×(xix0)2 \times(|x_i - x_0|)

请安排每一栋楼的坐标,使得这个人花费的时间最短。

TT 组数据。

对于 100%100\% 的数据,保证 1T103,1n2105,0ai1061\leq T \leq 10^3,1 \leq n \leq 2*10^5,0 \leq a_i \leq 10^6

解题思路

首先,我们把编号为 00 的楼的坐标定为 00 方便去做。

记答案为 ansans,则 ans=i=1n2aix0xians=\sum\limits_{i=1}^{n}{2*a_i*|x_0-x_i|}

要使得 ansans 最少,就要让 aia_i 大的楼放到距离 x0x_0 近的地方。

那么按照 aia_i 从大到小排序,在 x0x_0 按照左右左右左右…的顺序放楼即可。

具体实现见代码。

时间复杂度 O(Tn)\mathcal O(Tn)

CODE

#include <bits/stdc++.h>

using namespace std;

#define int long long

const int _ = 2e5 + 7;

int t;

int n;

struct abc
{
    int v, id;
} a[_];

int b[_];

int ans;

bool cmp(abc a, abc b)
{
    return a.v > b.v;
}

signed main()
{
    scanf("%lld", &t);
    while (t--)
    {
        ans = 0;
        scanf("%lld", &n);
        for (int i = 1; i <= n; ++i)
            scanf("%lld", &a[i].v), a[i].id = i;
        sort(a + 1, a + n + 1, cmp);
        int k = 0;
        for (int i = 1; i <= n; i += 2)
        {
            b[a[i].id] = ++k;
        }
        k = 0;
        for (int i = 2; i <= n; i += 2)
        {
            b[a[i].id] = --k;
        }
        for (int i = 1; i <= n; ++i)
        {
            ans += 2 * a[i].v * abs(b[a[i].id]);
        }
        cout << ans << "\n";
        cout << "0 ";
        for (int i = 1; i <= n; ++i)
            cout << b[i] << " ";
        cout << "\n";
    }
    return 0;
}
posted @ 2021-11-28 13:12  蒟蒻orz  阅读(6)  评论(0)    收藏  举报  来源