P10336 [UESTCPC 2024] 2-聚类算法

原题链接

闲话

本来是模拟赛题目, 但是过于古老, 于是就单独拿出来写了.

算法

博弈论, 套路题?

思路

考虑从答案入手, \(\displaystyle \textrm{val}(S_1) - \textrm{val}(S_2) = \sum_{i < j \in S_1} \textrm{dist}(i, j) - \sum_{i < j \in S_2} \textrm{dist}(i, j)\). 更进一步推导,

\[\sum_{i < j \in S_1} \textrm{dist}_{i, j} - \sum_{i < j \in S_2} \textrm{dist}_{i, j} \\ \begin{aligned} & = (\sum_{i < j \in S_1} \textrm{dist}(i, j) + \sum_{i < j \in S_2} \textrm{dist}(i, j) + \sum_{i \in S_1, j \in S_2} \textrm{dist}(i, j)) - (\sum_{i < j \in S_2} \textrm{dist}(i, j) + \sum_{i > j \in S_2} \textrm{dist}(i, j) + \sum_{i \in S_1, j \in S_2} \textrm{dist}(i, j)) \\ & = \sum_{i, j \in U} \textrm{dist}(i, j) - \sum_{i \in U, j \in S_2} \textrm{dist}(i, j) \end{aligned} \]

前一项为定值, 后一项只与 \(S_2\) 有关联.

所以对于 Alice 来说想让最大的点不计入贡献, 对于 Bob 来说想要尽可能选择大的点.

因此每个人的决策便是取当前到所有点距离和最大的点.

实现

在具体实现上, 由于 \(k\) 维是独立的, 我们可以分开算贡献即可.

//
// Created by Kang Lingrui on 2025/2/3.
//
#include "iostream"
#include "numeric"
#include "algorithm"

using namespace std;

#define int long long

constexpr int N = 2e5 + 10;

int n, k;
basic_string<int> x[N];

void init() {
    scanf("%lld %lld", &n, &k), n <<= 1;
    for (int i = 1; i <= n; ++i)
        for (int j = 1, y; j <= k; ++j) {
            scanf("%lld", &y);
            x[i].push_back(y);
        }
}

int id[N], d[N];

void calculate() {
    for (int j = 0; j < k; ++j) {
        iota(id, id + n + 1, 0);
        sort(id + 1, id + n + 1, [&](int a, int b) { return x[a][j] < x[b][j]; });
        int s = 0;
        for (int i = 1, t; i <= n; ++i) {
            t = id[i];
            d[t] += x[t][j] * i - s, s += x[t][j];
        }
        reverse(id + 1, id + n + 1), s = 0;
        for (int i = 1, t; i <= n; ++i) {
            t = id[i];
            d[t] += s - x[t][j] * i, s += x[t][j];
        }
    }
    sort(d + 1, d + n + 1, greater<>());
    __int128 ans = 0;
    for (int i = 1; i <= n; ++i) ans += d[i];
    ans /= 2;
    for (int i = 2; i <= n; i += 2) ans -= d[i];
    printf("%lld", (int)ans);
}

void solve() {
    init();
    calculate();
}

signed main() {
    solve();
    return 0;
}
posted @   Steven1013  阅读(3)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示