题目描述
还记得Matrix67的“非常男女”计划吗?由Matrix67策划的学校大型男女配对活动将在大礼堂隆重举行,学校里许多人即将前来捧场。大礼堂一共有n个座位,为了方便管理,Matrix67对它们从1到n顺序编号。售票工作已经完成,经统计,共有k个人拿到了入场券。由于k< n,因此大礼堂的座位完全足够。每张入场券上都印有座位号,入场者凭入场券对号入座。在这k个人即将陆续入场时,Matrix67发现了一个严重的错误:由于在入场券的销售过程中搞错了大礼堂总的座位数,入场券上印的座位号只有1到t。虽然这t个座位号中的每一个都在入场券中至少出现了一次,但有一个事实不能改变:t< k。也就是说,这k个人中有一些人的入场券上印有相同的座位号。这样,入场时必将发生很多次座位的争执。我们假定,当一个人入场后发现了他该坐的位置上已经有了人,此时这两个人将发生一次争执,争执的结果总是这个人不能夺回座位;此时该人继续寻找下一个座位号并可能再次发生争执,直到找到一个空位置为止。Matrix67必须调整这k个人的入场顺序,使得总的座位争执发生的次数最少。
输入格式
第一行有三个用空格隔开的正整数n、k、t,它们分别表示总的座位数、实际到场人数和入场券上的最大座位号,它们满足关系n>k>t。
第二行有k个用空格隔开的正整数。这些正整数保证不超过t,且所有不超过t的正整数总会在这些数中出现至少一次。它们表示这k个人的入场券上印的座位号。
对于30%的数据,n<=10;
对于50%的数据,n<=1000;
对于100%的数据,n<=100 000。
输出格式
输出发生争执的最少次数。
样例数据
样例输入
6 5 3
1 2 1 3 2
样例输出
6
样例说明
假设我们将入场顺序调整为1、1、3、2、2,下面说明此时发生的座位争执次数应该如何计算。
第一个人入场后成功找到1号座位。
第二个人入场后发现自己的入场券上印有的1号座位已经被占,此时发生一次争执;而后该人继续寻找2号座位并就座。
第三个人入场后成功找到3号座位。
第四个人入场后发现2号座位被占,争执后转而寻找3号座位并再次发生争执,直至成功找到4号座位。这里的争执有两次。
第五个人从2号座位开始寻找,接连三次寻找座位失败,最终在5号位置就座。这里一共发生了三次争执。
这样的入场方案使得总的争执数为6次。可以证明,不存在更好的入场顺序使得发生争执的次数少于6次。
题目分析
Matrix67你个坑货!还写个样例说明来骗我们入场顺序和争执次数毫无关系
结论1.前t个人入场必定将前t个座位坐满。
这一点应该没有问题吧。
结论2. t个座位号中的每一个都在入场券中出现过。
为什么呢?因为是题目原话啊23333
结论3.后面k-t个入场的人必定会发生争执,且依次坐在k-t个位置上。
由结论1显然
结论4.入场顺序和争执次数无关
假设前t个人没有发生争执,那么后k-t个人发生争执次数一定。为什么呢?由结论3显然。
接着,我们从k-t中间挑出一个人与前t个人座位号交换,那么增加的争执次数与减少的争执次数相同,由结论2推导而出,自己动手推算一下。
有了这些基础,模拟一遍就搞定了。
如果看不懂上面的结论,就当骗分吧。
源代码
#include<algorithm>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
inline const int Get_Int() {
int num=0,bj=1;
char x=getchar();
while(x<'0'||x>'9') {
if(x=='-')bj=-1;
x=getchar();
}
while(x>='0'&&x<='9') {
num=num*10+x-'0';
x=getchar();
}
return num*bj;
}
long long n,k,t,Hash[100005],sum=0;
int main() {
ios::sync_with_stdio(false);
n=Get_Int();
k=Get_Int();
t=Get_Int();
for(int i=1; i<=k; i++) {
int x=Get_Int();
if(Hash[x]==0)Hash[x]=1;
else {
t++;
sum+=t-x;
}
}
printf("%lld\n",sum);
return 0;
}