题意:有$n$个怪物,每个怪物有一个能力值$a[i]$,你现在有$m$个英雄,每个英雄有两个属性:$p[i]$表示这个英雄的能力值,$s[i]$表示这个英雄的耐力值,即一天内最多能消灭$s[i]$个怪物,每一天你可以选择一个英雄去消灭怪物,并且你只能一个一个的消灭,不能改变顺序,当一个英雄的能力值大于等于怪物的能力值并且他这一天内消灭的怪物数小于$s[i]$时,他就会继续去消灭下一个怪物,直到消灭的怪物数量等于$s[i]$或者这个英雄的能力值小于当前怪物的能力值,结束这一天,进入第二天,一个英雄可以使用多次,问消灭所有怪物最少的天数。
思路:当英雄最大的能力值小于怪物最大的能力值时,不可能把所有怪物消灭,直接输出$-1$,考虑有解时,显然当两个英雄的耐力值$s[i]$相等时,我们会选择能力值大的那个英雄去消灭怪物,所以我们定义$b[i]$表示耐力值至少为$i$(至少能消灭$i$只怪)的英雄中最大的能力值,显然$b[i]$从$n$到$1$是非递减的。设在某一天内已经消灭了$k$只怪物,因为一天只能选择一个英雄,所以在消灭第$k+1$只怪物时,如果这一天内怪物能力的最大值$now$大于$b[k+1]$,则应该结束这一天,第二天又从最大值$b[1]$开始消灭怪物。
注意:$b[i]$数组的求法,从后先前,每次$b[i]=max(b[i],b[i+1])$
#include <iostream> #include <algorithm> #include <cstdio> using namespace std; const int N = 200010; int t, n, m, b[N], a[N]; int main() { scanf("%d", &t); while (t--) { scanf("%d", &n); for (int i = 1; i <= n; i++) b[i] = 0; int mmo = -1, mp = -1; for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); mmo = max(mmo, a[i]); } scanf("%d", &m); for (int i = 1; i <= m; i++) { int p, s; scanf("%d%d", &p, &s); mp = max(mp, p); b[s] = max(b[s], p); } for (int i = n - 1; i >= 1; i--) b[i] = max(b[i + 1], b[i]); if (mp < mmo) { printf("-1\n"); continue; } int now = -1, k = 0, ans = 0; for (int i = 1; i <= n; i++) { now = max(now, a[i]), k++; if (b[k] < now) { ans++, k = 1, now = a[i]; } } printf("%d\n", ans + 1); } return 0; }
原文地址:https://www.cnblogs.com/zzzzzzy/p/11886348.html
时间: 2024-11-05 21:48:05