题意:
有n个怪兽,每个怪兽的战斗力为a[i]。
有m个英雄,每个英雄都有两个属性pi(战斗力)和si(耐力值),每杀死一个怪兽耐力值-1。
每天都需要派一个英雄去杀怪兽,如果该英雄的战斗力低于怪兽或者耐力值没了,则这一天结束。
问你最少多少天能杀完怪兽?
思路:
用k[i]数组记录每个耐力值的最大攻击力值
再按攻击力值填充耐力值为0的地方,比如k[2]=8说明耐力值为2的攻击力为8 没有耐力值为1的所以k[1]=0
这时 令k[1]=8,说明耐力值为1的攻击力为8,表明当攻击力为8时,我可以攻打一个,也可以攻打两个
反向填充,耐力值逐渐减少而攻击力取最大值,意在原攻击力匹配k个耐力值,可以都用,或者用一个,或者用两个。。等等
也会取代耐力值小并且攻击力也小的英雄
for (int i = n; i >= 0; i--) k[i] = max(k[i], k[i + 1]);
对于每个a[i]与k[1]比较,此时k[1]为英雄攻击力最大值,若是任一a[i]大于k[1]说明无法成功,输出-1。
之后遍历怪兽的攻击力,取a[i+j]和a[i+j+1]的最大值与英雄耐力值为j+1时的攻击力比较,
一旦英雄攻击失败,天数++,并且记录此时的i(i为第几只怪兽),再接着遍历
for (; j <= n; j++) {
maxn = max(maxn, a[j + i]);
if (k[j + 1] < maxn) break; //因为每个英雄可以无限次使用
}
day++;
i += j;
按顺序攻击,所以k数组的目的就是在攻击力可以的情况下使耐力尽可能大。
注意:英雄是按顺序攻击怪兽,若是这个英雄没有攻击成功,下一个英雄第二天继续攻击
每天都会生成新的耐力值
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #include<stack> 7 #include <bitset> 8 #include<set> 9 #include<map> 10 #include<unordered_map> 11 #include<vector> 12 #include<cmath> 13 #include<string> 14 using namespace std; 15 typedef long long ll; 16 #define inf 99999999 17 const int maxn = 2e5; 18 int t, n, m; 19 int a[maxn], k[maxn]; 20 struct node { 21 int p; 22 int s; 23 }her[maxn]; 24 int main() { 25 cin >> t; 26 while(t--){ 27 cin >> n; 28 for (int i = 1; i <= n; i++) { 29 cin >> a[i]; 30 } 31 cin >> m; 32 for (int i = 1; i <= m; i++) { 33 cin >> her[i].p >> her[i].s; 34 //记录每个耐力值的最大攻击力值 35 k[her[i].s] = max(k[her[i].s], her[i].p); 36 } 37 for (int i = n; i >= 0; i--) k[i] = max(k[i], k[i + 1]); 38 int day = 0; 39 int f = 0; 40 for (int i = 1; i <= n;) { 41 if (a[i] > k[1]) { 42 f = 1; 43 cout << "-1" << endl; 44 break; 45 } 46 int j = 0; 47 int maxn = 0; 48 for (; j <= n; j++) { 49 maxn = max(maxn, a[j + i]); 50 if (k[j + 1] < maxn) break; //因为每个英雄可以无限次使用 51 } 52 day++; 53 i += j; 54 } 55 if (f == 0) { 56 cout << day << endl; 57 } 58 for (int i = 0; i <= n; i++) k[i] = 0; 59 } 60 return 0; 61 }