[vijos1245] 座位的争执

版权声明:全文无版权,目前博客已搬迁至https://bill.moe https://blog.csdn.net/Bill_Yang_2016/article/details/54863768

题目描述

还记得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;
}

展开阅读全文

没有更多推荐了,返回首页