小P别急
题目链接:SSL 1533
题目大意
要你维护三种操作,新加入一个怪;有名字和血量,给当前所有怪造成 x 的伤害,如果血量小于等于 0 就死亡;询问在场血量最高的怪的名字和血量,并将其杀死。
思路
考虑模拟过程,发现要维护的是血量最大的。
但是它扣血是全体扣血,并不会改变谁是最大。
考虑不要直接扣血,而是记着从头开始已经扣了多少血,新加进来的就给他加上当前扣了的血量。
然后我们用一个堆维护,每次取出来先判断一下是不是已经没血了就行。
代码
#include<queue>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
const int N = 1e6 + 100;
int n, m, nsz[N];
char name[N][21];
ll di;
ll re, zf; char c;
ll read() {
re = 0; zf = 1; c = getchar();
while (c < '0' || c > '9') {
if (c == '-') zf = -zf; c = getchar();
}
while (c >= '0' && c <= '9') {
re = (re << 3) + (re << 1) + c - '0';
c = getchar();
}
return re * zf;
}
priority_queue <pair<ll, int> > q;
int main() {
freopen("mega.in", "r", stdin);
freopen("mega.out", "w", stdout);
n = read();
for (int i = 1; i <= n; i++) {
int op = read();
if (op == 1) {
scanf("%s", name[++m] + 1);
nsz[m] = strlen(name[m] + 1);
ll hp = read() + di;
q.push(make_pair(hp, m));
}
if (op == 2) {
ll x = read();
di += x;
}
if (op == 3) {
if (q.empty() || q.top().first <= di) {
printf("Air 0\n");
}
else {
pair <ll, int> now = q.top(); q.pop();
for (int i = 1; i <= nsz[now.second]; i++) putchar(name[now.second][i]);
putchar(' '); printf("%lld\n", now.first - di);
}
}
}
return 0;
}