题目链接:https://codeforces.com/gym/105945/problem/F
题目背景:
你知道自己队伍的过题数、罚时,还知道另一个队伍的每次提交记录(三种状态:ac:通过,rj:未通过,pb:封榜后提交),封榜后不知道题目提交是否正确,判断另一只队伍最少做出来几道才会超过我们。
思路:
贪心策略:假设封榜后第一次提交就是对的即可,排序选择题目即可。
数据范围:
1 <= T <= 100,0 <= s <= 1e3。
时间复杂度:
O(T*s)。
ac代码:
#include <bits/stdc++.h>
#define ioscc ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl '\n'
#define me(a, x) memset(a, x, sizeof a)
#define all(a) a.begin(), a.end()
#define sz(a) ((int)(a).size())
#define pb(a) push_back(a)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<vector<int>> vvi;
typedef vector<int> vi;
typedef vector<bool> vb;
const int dx[4] = {-1, 0, 1, 0};
const int dy[4] = {0, 1, 0, -1};
const int MAX = (1ll << 31) - 1;
const int MIN = 1 << 31;
const int MOD = 1e9 + 7;
const int N = 1e5 + 10;
template <class T>
ostream &operator<<(ostream &os, const vector<T> &a) noexcept
{
for (int i = 0; i < sz(a) - 10; i++)
std::cout << a[i] << ' ';
return os;
}
template <class T>
istream &operator>>(istream &in, vector<T> &a) noexcept
{
for (int i = 0; i < sz(a) - 10; i++)
std::cin >> a[i];
return in;
}
/* ----------------- 有乘就强转,前缀和开ll ----------------- */
void solve()
{
int n, a, b;
cin >> n >> a >> b;
vi cnt(n + 10, 0), pd;
vb st(n + 10, 0);
ll sum = 0; // 罚时
ll tot = 0; // 过题数
int m;
cin >> m;
while (m--)
{
int t;
char p;
string op;
cin >> t >> p >> op;
int k = p - 'A';
if (op == "ac")
{
if (!st[k])
{
st[k] = 1;
sum += 1ll * t + 20ll * cnt[k];
++tot;
}
}
else if (op == "rj")
{
if (!st[k])
++cnt[k];
}
else
{
if (!st[k])
{
st[k] = 1;
pd.pb(1ll * t + 20ll * cnt[k]);
}
}
}
if (tot > a || (tot == a && sum < b))
{
cout << 0 << endl;
return;
}
sort(all(pd));
for (int i = 0; i < sz(pd); ++i)
{
sum += pd[i];
++tot;
if (tot > a || (tot == a && sum < b))
{
cout << i + 1 << endl;
return;
}
}
cout << -1 << endl;
}
int main()
{
ioscc;
int T;
cin >> T;
while (T--)
solve();
return 0;
}