原题链接:
https://ac.nowcoder.com/acm/contest/9692
题意:
- 这题就是说有m个嘉宾抢最多n个座位,抢不到心仪的座位就只能继续往前走,还得生气,怒气值就是这位嘉宾多走了几个座位。
题解:
- 要尽量让怒气值最小,也就是走过的距离最小,那肯定得啪的一下看到心仪座位后的空的座位嘉宾就马上坐下。
- 那么我们假设有无数个座位供嘉宾们坐下,记最后一个嘉宾坐下的位置为p,若p > n就说明座位不够,输出-1,否则输出怒气值的和。
实现:
- 先让这m个嘉宾的心仪座位(假设有四个)从小到大排序,分别记为m1,m2,m3,m4。座位靠前的先进去,啪的一下就坐下来了并且马上占据了这个座位,那很显然p的长度马上就变成了m1,并且下一个人至少从第p+1(或者说m1+1)个座位开始坐下。
- 如果m2 < p+1,m2嘉宾只能生[(p+1) - m2](当然此处是一)格的气并且坐下,此时p又得加一,下一个人最少只能坐p+2了。
- 如果m2 >= p+1,那m2嘉宾就可以坐到自己心仪的位置上了。如果这个时候最后一个座位p已经变成了m2,下一个人又只能坐p++(或者说m2++也行)了。
- 还记得我们对m排序了吗,也就说明一定有m3 >= m2,那我们就又可以重复刚刚的行为了耶!!
- 最后我们的m4嘉宾坐下来了,此时的p就是我们需要的座位个数。
代码:
#include <bits/stdc++.h>
//
using namespace std;
const int mod = 1e9+7;
typedef unsigned long long ull;
typedef long long ll;
typedef long double ld;
#include <bits/stdc++.h>
using namespace std;
int main()
{
long long n, m;
long long num [100005];
scanf("%lld %lld", &n, &m);
for(int i = 1;i <= m;i++)
{
scanf("%lld", &num[i]);
}
sort(num+1, num+m+1);
long long p = 1;
long long ans = 0;
//参照了一下别人的代码
//这个p就是座位,如果你的座位符合你就坐下去,同时这个座位已经被占了,p就得++
//如果你座位已经被占了,你就得往后走一个位置再坐下
for(int i = 1;i <= m;i++)
{
if(p <= num[i])
{
p = num[i];
p++;
}
else
{
ans += p - num[i];
if(i < m) p++;
}
}
//要是你比最多的座位还多,那你就没办法坐下了
if(p > n) ans = -1;
printf("%lld", ans);
return 0;
}