打怪兽(模拟排序,暑假集训训练赛)
题目来源:https://codeforces.com/problemset/problem/1763/B
//
题意:n个怪兽,每个怪兽都有自己的生命值,攻击力属性,作为奥特曼,初始有自己的伤害值k,每次对每个怪兽攻击k点伤害后,奥特曼的伤害值会削弱,还存活的怪兽种的最小攻击力。问奥特曼是否能杀死所有的怪兽?
//
思路:“这个sb题啊,模拟的时候,就是有一个地方,时间复杂度会很高,就是某些怪兽死亡后,怎么又重新去维护存活的怪兽的最小攻击力,当时每次打一次怪兽后,都去遍历一边哪些怪兽死亡了,然后又sort一次,tle。然后又优化,判断最小攻击力的怪兽是否死了,死了再重sort,否则不管,其中这个地方离正解也不远了。”难点就是怎么去更新死掉的怪兽的攻击力。其中,我们只关心攻击力最小的怪兽死没死,是不是?所以对攻击力sort一次后,每次更新削弱伤害值,改成会造成伤害的总伤害值,只先看攻击力最小的怪兽死没,死了再后移一个就行了,最后直到伤害值加不了了。此时能造成怪兽的总伤害值也记录好了,但是后面存在攻击力很大,但是生命值很小的怪兽,没有来得及杀,所以要重新遍历一次,重杀一边。
//
题解:
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e5 + 10;
const int mod = 1e9 + 7;
#define pii pair<int, int>
int n, k, h[N], p[N];
struct node
{
int h, p;
bool operator<(const node x) const
{
return p < x.p;//攻击力排序
}
} a[N];
void solve()
{
cin >> n >> k;
for (int i = 1; i <= n; i++)
cin >> a[i].h;
for (int j = 1; j <= n; j++)
cin >> a[j].p;
sort(a + 1, a + n + 1);
int cnt = 0, u = 1; // cnt为当前总的攻击值,u为当前p最小的怪兽下标
while (k > 0)
{
cnt += k;//总伤害
int mn = 1e9;
while (u <= n && a[u].h - cnt <= 0) // h值已经小于0,看攻击力最小的你杀不杀得死,死就u++,一直杀,杀到攻击力削弱到0,就杀不动了
u++;
if (u == n + 1) // 所有的怪兽的h都小于了0,都杀完了
{
puts("YES");
return;
}
mn = a[u].p;
k -= mn;
}
for (int i = 1; i <= n; i++)//存在攻击力小的血厚实,后面攻击力大的血薄的,没杀到,重杀
{
if (a[i].h - cnt > 0) // 当有怪兽杀不死
{
puts("NO");
return;
}
}
puts("YES");
}
signed main()
{
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int T;
cin >> T;
while (T--)
solve();
}
点击查看代码
#include<iostream>
#include<cmath>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<algorithm>
#include<cctype>
#include<cstring>
#include<list>
#define int long long
using namespace std;
const int N = 5e5+10;
int mod;
bool f = false;
int h[N], p[N];
set<pair<int,int> >a, b;
int n, m, x, y, le, ri, ans, num, max1, min1 = 0x3f3f3f3f;
void solve() {
a.clear();
b.clear();
cin >> n >> m;
for (int i = 0; i < n; i++) {
cin >>h[i];//生命值
}
for (int i = 0; i < n; i++) {
cin >> p[i];//攻击力
a.insert({ h[i],p[i] });//用生命值进行排序
b.insert({ p[i],h[i] });//攻击力排序
}
x = 0;
while (!a.empty()&&m>0){
x += m;//总攻击力
while (!a.empty() && (*a.begin()).first <= x){//死亡
int xue = (*a.begin()).first;//死亡的血量
int gongji = (*a.begin()).second;//死亡的攻击力
a.erase(a.begin());//删除死亡的
b.erase(b.find({ gongji,xue }));//同时删除死亡的攻击力,通过死亡的xue和攻击力查找
}
m -= (*b.begin()).first;
}
if (a.empty())
cout << "YES" << endl;
else
cout << "NO" << endl;
return;
}
signed main() {
int _ = 1;
cin >> _;
while (_--) {
solve();
}
return 0;
}
浙公网安备 33010602011771号