11379: 送分题
时间限制: 1 Sec 内存限制: 128 MB
提交: 78 解决: 8
[提交] [状态] [命题人:admin]
题目描述
有2n个人排队上厕所。厕所只有两个单间,一个是男女通用的单间,一个是女性专用的单间。所有人都排成一队,如果当前队首是女性,她会优先进入女性专用单间,如果已经被占用则进入男女通用单间,如果男女通用单间也被占用就只好等着了;如果当前队首是男性,他会尝试进入男女通用单间,如果已经被占用他就会继续等待,此时如果女性专用单间为空,当前队列里最前的一位女性会直接进入。
我们假设每个人上厕所需要一个单位的时间,在队列中移动的时间忽略不计。你希望调整队列顺序使得在n个单位时间内所有人都上完厕所。调整顺序可能会引起不满,一个人的不满值定义为调整队列前在他之后且调整队列后在他之前的人数,你希望使得所有人中最大的不满值尽可能小。
输入
第一行一个正整数n。
队列以一种特殊的形式给出,首先第二行会给出一个正整数m,接下来m行,每行一个字符串和一个数字x,这一行描述的字符串为给出的字符串重复x次后得到的字符串。把每一行描述的字符串接起来即可得到描述整个队列的字符串。描述整个队列的字符串按队列从前到后的顺序依次给出每个人的性别,M表示男性,F表示女性。
输出
输出一个整数,表示最小的最大不满值。如果没有重排方案使得在n个单位时间内所有人都上完厕所,输出−1。
样例输入
复制样例数据
2 2 F 2 M 2
样例输出
1
提示
对于100%的数据,n≤1018,m≤105,给出的字符串总长不超过2×105。
题意:有两个厕所1、2,女性可以到这两个厕所,并且优先去1厕所,男性只可以去2厕所,若此时2被占用,1空着,队伍中最前面的女性可以去1厕所
训练赛时没看懂输入的那个复读是什么意思。。。
题解:举一个例子可以发现男性的数量不可以多于女性,否则肯定不可行
假设女性加1,男性减1,那么可以推出后缀和小于-1时,方案不可行,这时只能让男性尽量靠前,不满值就主要由女性贡献
因为要求某一个最大的不满值最小,那么不管男性移几位都不影响答案,所以就移到最前面
输入的话,就每段分别处理计算后缀和
接着来自 大佬的博客
最后一段需要把后缀和最大值个的M移到队首,而前面的k−1k−1段就只需要把max(F的个数 - M的个数)的M移走即可。
通过这个方法得出的数列一定满足每次匹配都是'MF'的情况(M消耗完后则为'FF')
但是我们允许'FM'的状况出现。
所以我们可以少移一次。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 100;
string s;
ll minn[maxn];
ll p[maxn];
ll num[maxn];
int main() {
int m;
ll n;
scanf("%lld%d", &n, &m);
ll tot = 0;
for (int i = 1; i <= m; i++) {
cin >> s >> num[i];
int l = s.length();
for (int j = l - 1; j >= 0; j--) {
p[i] += (s[j] == 'F' ? 1 : -1);
minn[i] = min(minn[i], p[i]);
}
tot += p[i] * num[i];
}
if (tot < 0) {
puts("-1");
return 0;
}
ll ans = 0;
tot = 0;
for (int i = m; i > 0; i--) {
if (p[i] > 0) ans = min(ans, tot + minn[i]);
else ans = min(ans, tot + (num[i] - 1) * p[i] + minn[i]);
tot += p[i] * num[i];
}
printf("%lld\n", max(0ll, -ans - 1));
return 0;
}