可以用若干个优先队列每一种员工可能会参与到的所有项目,从小到大排序
给每一个项目加上若干个限制,每有一种员工达到要求,限制就减一,限制为0时就收获这个项目的奖励
可以将每次奖励存到队列中去,每次奖励使某种员工增加时,就看这种员工可能参加的剩余的项目中有没有能减少限制的
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'
using namespace std;
typedef pair<int, int> PII;
typedef long long ll;
typedef long double ld;
typedef pair<ll, int> PLI;
const int N = 100010;
int res[N];//每个项目的限制
map<int, ll> have;//每种员工有多少人
map<int, priority_queue<PLI, vector<PLI>, greater<PLI>>> q;//每种员工下的项目需要人数
vector<PII> reward[N];
int ans;
int main()
{
IOS
int n;
cin >> n;
for(int i = 0; i < n; i ++)
{
int a, b;
cin >> a >> b;
have[a] = b;
}
queue<PII> q_rew;
cin >> n;
for(int i = 1; i <= n; i ++)
{
int m;
cin >> m;
for(int j = 0; j < m; j ++)
{
int a, b;
cin >> a >> b;
if(b > have[a])
{
res[i] ++;
q[a].push({b, i});
}
}
cin >> m;
for(int j = 0; j < m; j ++)
{
int a, b;
cin >> a >> b;
reward[i].push_back({a, b});//a类员工,b个人
}
if(!res[i])
{
ans ++;
for(int j = 0; j < m; j ++)
{
q_rew.push({reward[i][j].first, reward[i][j].second});
}
}
}
while(q_rew.size())
{
int A = q_rew.front().first, B = q_rew.front().second;
q_rew.pop();
have[A] += B;
while(q[A].size())
{
int t = q[A].top().first;
if(t > have[A])break;
int num = q[A].top().second;
q[A].pop();
res[num] --;
if(!res[num])
{
ans ++;
for(int i = 0; i < reward[num].size(); i ++)
{
int a = reward[num][i].first, b = reward[num][i].second;
q_rew.push({a, b});
}
}
}
}
cout << ans;
return 0;
}