题意:
有若干个班,每个班有些人要喝奶茶,也提供一些奶茶,一人喝一杯,但是自己班的人不能喝自己班的奶茶,求最多能有多少人喝上奶茶。
题解:
先按班级人数从大到小排序。
为防止自己班的人喝到自己班的奶茶,设立一个缓冲区,储存前面的班喝剩下的奶茶。
如果后面的班有奶茶,抢后面班的奶茶喝,如果后面班的奶茶喝完了,就去看缓冲区还剩不剩奶茶。
最后自己班的人喝完了或者没得喝了,再把自己班还没被前面班的人抢光的奶茶放到缓冲区里。
然后轮到下一个班,再执行如上步骤。
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef long long ll; typedef pair<int, LL>P; const int M = 4e5 * 4 + 5; const LL mod = 1e9 + 7; const LL lINF = 0x3f3f3f3f3f3f3f3f; #define ls (rt<<1) #define rs (rt<<1|1) LL gcd(LL a, LL b) { return b ? gcd(b, a%b) : a; } LL quickpow(LL a, LL b, LL mod) { LL res = 1; while (b) { if (b & 1) res = (res*a) % mod; a = (a*a) % mod; b >>= 1; } return res; } struct node { LL a, b; }tr[M]; int t; int n; LL cnt; LL ans; int lid; bool cmp(node x, node y) { return x.b > y.b; } int main() { scanf("%d", &t); while (t--) { scanf("%d", &n); for (int i = 1; i <= n; i++) { scanf("%lld%lld", &tr[i].a, &tr[i].b); } sort(tr + 1, tr + 1 + n, cmp); ans = cnt = 0; lid = 2; for (int i = 1; i <= n; i++) { while (lid < i) { cnt += tr[lid].a; lid++; } if (lid == i) lid++; while (tr[i].b) { if (lid <= n) { LL tmp= min(tr[lid].a, tr[i].b); ans += tmp; tr[i].b -= tmp; tr[lid].a -= tmp; if(!tr[lid].a) lid++; } else { LL tmp= min(tr[i].b, cnt); ans += tmp; tr[i].b -= tmp; cnt -= tmp; if (!cnt) break; } } cnt += tr[i].a; tr[i].a = 0; } printf("%lld\n", ans); } }