首页 > 编程语言 >洛谷P10336 [UESTCPC 2024] 2-聚类算法

洛谷P10336 [UESTCPC 2024] 2-聚类算法

时间:2024-10-04 12:11:42浏览次数:8  
标签:洛谷 int sum Alice 距离 UESTCPC P10336 getchar dis

涉及知识点:博弈、贪心

题意

Alice 和 Bob 在玩选点游戏,所有的点在一个 \(k\) 维空间中,他们轮流选走一个点放入自己的集合中,Alice 先手。定义集合 \(S\) 的权值 \(val(S)\) 为集合中点两两之间的 \(k\) 维曼哈顿距离之和。Alice 的得分为 \(val(S_A)-val(S_B)\),Bob 的得分为 \(val(S_B)-val(S_A)\),两人都想最大化自己的得分且采用最优策略,请问 Alice 最终得分为多少。

有 \(2n\) 个点,\(1\leq n\times k\leq 10^5\)。

思路

将得分表示出来进行转换,则 Alice 的得分显然为:

\[\sum_{i,j\in S_A,i<j}dis(i,j)-\sum_{i,j\in S_B,i<j} \]

此时两边同时加上 \(\sum_{i,j\in S_B,i>j}dis(i,j)+\sum_{i\in S_A,j\in S_B}dis(i,j)\):

\[\begin{equation*} \begin{aligned} &[\sum_{i,j\in S_A,i<j}dis(i,j)+\sum_{i,j\in S_B,i>j}dis(i,j)+\sum_{i\in S_A,j\in S_B}dis(i,j)]-[\sum_{i,j\in S_B,i<j}dis(i,j)+\sum_{i,j\in S_B,i>j}dis(i,j)+\sum_{i\in S_A,j\in S_B}dis(i,j)] \\ =& [\sum_{i,j\in S_A,i<j}dis(i,j)+\sum_{i,j\in S_B,i<j}dis(i,j)+\sum_{i\in S_A,j\in S_B}dis(i,j)]-[\sum_{i,j\in S_B}dis(i,j)+\sum_{i\in S_A,j\in S_B}dis(i,j)] \\ =& \sum_{i,j\in S_A\cup S_B,i<j}dis(i,j)-\sum_{i\in S_A\cup S_B,j\in S_B}dis(i,j) \end{aligned} \end{equation*} \]

因此,Alice 的得分为空间中所有点两两之间的距离之和减去所有点到 \(S_B\) 的距离之和,前者是一个固定值,因此 Alice 想要得分更高,就必须要使得 \(S_B\) 中的点到所有点距离和最小,她得抢在 Bob 前把距离和大的点放到 \(S_A\) 中;然而由于 Bob 的得分是 Alice 的相反数,所以他想使得 \(S_B\) 中的点到所有点距离和最大,他想尽可能取距离和大的点放在 \(S_B\) 中。因此我们将每个点到所有点的距离和算出来并大到小排序,Alice 和 Bob 轮流取最大的点。

另一种很精彩的说法:

将边权化为点权,每个点的点权设为自己到其他所有点的距离之和,这样一来假设两个点 \(a,b\) 分别属于 \(S_A,S_B\) 那么它们点权相减时,它们之间的距离正好可以抵消;假设两个点属于同一个集合,那么它们之间的距离就会被算两次。因此 Alice 的得分即为 \(\frac{\sum S_A-\sum S_B}{2}\)。

那么,如何计算一个点到所有点的距离和呢?肯定不能直接 \(O(n^2k)\) 计算。这里涉及一个小 Trick,由于曼哈顿距离的计算维度之间是不相干扰的,因此可以将每维拆开来计算,将所有点在该维度上的位置从小到大排序,再用前后缀和来计算,这么做是 \(O(kn\log n)\) 的,具体可以参考代码 52-61 行。

代码

用的是此处的答案统计方式。

#include<bits/stdc++.h>
using namespace std;
#ifdef ONLINE_JUDGE
#define getchar __getchar
inline char __getchar(){
    static char ch[1<<20],*l,*r;
    return (l==r&&(r=(l=ch)+fread(ch,1,1<<20,stdin),l==r))?EOF:*l++;
}
#endif
template<class T>inline void rd(T &x){
    T res=0,f=1;
    char ch=getchar();
    while(ch<'0' || ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    while('0'<=ch && ch<='9'){res=res*10+ch-'0';ch=getchar();}
    x=res*f;
}
template<class T>inline void wt(T x,char endch='\0'){
    static char wtbuff[20];
    static int wtptr;
    if(x==0){
        putchar('0');
    }
    else{
        if(x<0){x=-x;putchar('-');}
        wtptr=0;
        while(x){wtbuff[wtptr++]=x%10+'0';x/=10;}
        while(wtptr--) putchar(wtbuff[wtptr]);
    }
    if(endch!='\0') putchar(endch);
}
typedef pair<int,int> pii;
typedef long long LL;
const int MAXN=2e5+5;
int n,k;
vector<int>v[MAXN];
vector<pii>dim;
LL dissum[MAXN],ans=0;
int main(){
    freopen("ys.in","r",stdin);
    freopen("ys.out","w",stdout);
    rd(n);rd(k);
    for(int i=1;i<=2*n;i++){
        v[i].resize(k);
        for(int j=0;j<k;j++){
            rd(v[i][j]);
        }
    }
    for(int i=0;i<k;i++){
        dim.clear();
        for(int j=1;j<=2*n;j++) dim.emplace_back(v[j][i],j);
        sort(dim.begin(),dim.end());
        LL presum=0;
        for(int j=0;j<dim.size();j++){
            dissum[dim[j].second]+=1LL*dim[j].first*j-presum;
            presum+=dim[j].first;
        }
        presum=0;
        for(int j=dim.size()-1;j>=0;j--){
            dissum[dim[j].second]+=presum-1LL*dim[j].first*(dim.size()-1-j);
            presum+=dim[j].first;
        }
    }
    sort(dissum+1,dissum+1+2*n,greater<LL>());
    for(int i=1;i<=2*n;i+=2)
        ans+=dissum[i]-dissum[i+1];
    wt(ans/2);
    return 0;
}

标签:洛谷,int,sum,Alice,距离,UESTCPC,P10336,getchar,dis
From: https://www.cnblogs.com/SkyNet-PKN/p/18446489

相关文章

  • 题解:洛谷P2339 [USACO04OPEN] Turning in Homework G
    题目链接:洛谷P2339[USACO04OPEN]TurninginHomeworkG首先我们考虑如何处理到达给定时间后才能交作业这一限制。其实在生活中,我们一般只会考虑什么时候交作业截止(除了某些卷王),这样我们只用考虑如何在最大结束时间之前交作业,而不是在所有作业都没开始交之前考虑如何转悠(前者明......
  • 20241002每日一题洛谷P1563
    粗看题目我靠,什么方向还变来变去的(哭泣核心思想:圈内右数,圈外左数为整体逆时针数;圈外右数,圈内左数为整体顺时针数运用结构体就有了第一版源码://///define_CRT_SECURE_NO_WARNINGS1include<stdio.h>includestructpeople{intface;charname[12];};intmain(){in......
  • 【LGR-197-Div.2】洛谷 10 月月赛 I &「SFMOI」Round I(A,B,C)
    A.StrangeCakeGame对于小W,往下走最赚,对于小M往右走最赚,于是路线形成了个折线,直接对应竖坐标位置去看看横坐标符不符合要求即可#include<iostream>#include<algorithm>#include<string>#include<string.h>#include<queue>#include<deque>#include<math.h>#include<m......
  • 洛谷P1518两只塔姆沃斯牛
    #include<bits/stdc++.h>usingnamespacestd;usingi64=longlong;usingu64=unsignedlonglong;usingu32=unsigned;charm[12][12];intfarmer[3];intcow[3];boolzt[200000];intans;voidmove(intx,inty,intdir,inttype){if(dir==......
  • 【洛谷】AT_abc079_d [ABC079D] Wall 的题解
    【洛谷】AT_abc079_d[ABC079D]Wall的题解洛谷传送门AT传送门题解不懂就问,为什么ABC很喜欢出板子题。经典的Floydqaq题目给出了一个二维数组和000~......
  • (洛谷)题目题号P1047 [NOIP2005 普及组] 校门外的树
    Hello大家好我是小亦,这是今天发布的第二篇题解,唉我就在想怎么样才能把粉丝提上来呢隔壁朋友都比我高了好多唉苦恼qwq,好吧接受现实,好那么好今天我们来讲的是来自于NOIP2005年普及组的真题名叫:校门外的树,其实这道题跟其他几道题很相似,应该是同一家的吧qwq,好了不废话了思路给大家q......
  • 数组中洛谷p1427小鱼的数字游戏
    先来看看题目吧:然后先来复习一下数组:你需要了解:数组的定义,数组的创建,数组的初始化,数组的使用(尤其是数组下标是从零开始的!)然后就来看思路吧:......
  • 洛谷题单指南-分治与倍增-P6648 [CCC2019] Triangle: The Data Structure
    原题链接:https://www.luogu.com.cn/problem/P6648题意解读:在一个n行的数字三角形中,求所有边长为k的正三角形最大值之和。解题思路:1、枚举法枚举每一个边长为k的三角形,在其中求max,然后累加,n最多3000,时间复杂度是n^4,显然超时。2、倍增和ST思想此题非常类似于RMQ问题,也就是求区......
  • 字符串中洛谷B2124判断字符串是否为回文
     #include<stdio.h>intmain(){  charstr[80];  inti,count=0;  intt=0;   gets(str);//输入   for(i=0;str[i]!='\0';i++)//遇到字符串结束标志'\0'时停止计数    count++;//统计共有多少个字符   for(i=0;i<count/2;i++......
  • 洛谷每日一题(P2580 于是他错误的点名开始了)字典树/哈希表
    原题目链接:P2580于是他错误的点名开始了-洛谷|计算机科学教育新生态(luogu.com.cn)原题目截图:思路分析:解法一:哈希表法显而易见的一种思路,我们不妨模拟一下:当教练每次点名,我作为特派员,便查看一下有没有这个学生,是不是点过了这个学生。我们查看的过程,就依赖于一张表......