142 lines
3.5 KiB
C++
142 lines
3.5 KiB
C++
|
#include <iostream>
|
||
|
#include <vector>
|
||
|
#include <algorithm>
|
||
|
|
||
|
using namespace std;
|
||
|
|
||
|
//#define ENABLE_LOG
|
||
|
|
||
|
struct snake {
|
||
|
int id;
|
||
|
int power;
|
||
|
|
||
|
snake(int id, int power) {
|
||
|
this->id = id;
|
||
|
this->power = power;
|
||
|
}
|
||
|
|
||
|
bool operator<(const snake &obj) const {
|
||
|
if (obj.power == power) return obj.id < id;
|
||
|
return obj.power < power;
|
||
|
}
|
||
|
|
||
|
bool operator>=(const snake &obj) const {
|
||
|
return power >= obj.power;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
bool sort_by_id(snake a, snake b) {
|
||
|
return b.id > a.id;
|
||
|
}
|
||
|
|
||
|
void eat(vector<snake> &vec, bool skip_sort = false) {
|
||
|
if (vec.size() < 2) return;
|
||
|
if (!skip_sort) {
|
||
|
sort(vec.begin(), vec.end());
|
||
|
}
|
||
|
|
||
|
#if defined(ENABLE_LOG)
|
||
|
for (auto item: vec) {
|
||
|
printf("eating log: \n");
|
||
|
printf("(%d, %d)\n", item.id, item.power);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
if (!(vec[0] >= vec[vec.size() - 1])) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// If this snake ate the last snake
|
||
|
snake curr = vec[0];
|
||
|
snake last = vec[vec.size() - 1];
|
||
|
#if defined(ENABLE_LOG)
|
||
|
printf("%d gonna to eat %d\n", curr.id, last.id);
|
||
|
#endif
|
||
|
vec.pop_back();
|
||
|
vec[0].power -= last.power;
|
||
|
sort(vec.begin(), vec.end());
|
||
|
if (vec[0].id != curr.id) {
|
||
|
bool will_be_eaten = false;
|
||
|
int strongest_curr_power = vec[0].power;
|
||
|
// Looking up if current snake will be eaten
|
||
|
for (auto it = vec.rbegin(); it < vec.rend(); it++) {
|
||
|
if (strongest_curr_power >= it->power) {
|
||
|
if (it->id == curr.id) {
|
||
|
// So bad, the new strongest snake will eat the current strongest snake
|
||
|
// Give up eating right now!
|
||
|
will_be_eaten = true;
|
||
|
break;
|
||
|
}
|
||
|
// No more thinking, just go for it
|
||
|
strongest_curr_power -= it->power;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (will_be_eaten) {
|
||
|
#if defined(ENABLE_LOG)
|
||
|
printf("%d give up, cuz it will be eaten after ate that snake, new strongest snake %d\n", curr.id,
|
||
|
vec[0].id);
|
||
|
#endif
|
||
|
// It means the current snake going to be eaten
|
||
|
// Revert the action
|
||
|
for (auto &item: vec) {
|
||
|
if (item.id == curr.id) {
|
||
|
item.power = curr.power;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
vec.push_back(last);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#if defined(ENABLE_LOG)
|
||
|
printf("%d has ate %d\n", curr.id, last.id);
|
||
|
#endif
|
||
|
// Else, it means the current snake is still strong enough
|
||
|
// Going to see other snakes can be eaten...
|
||
|
return eat(vec, skip_sort = true);
|
||
|
}
|
||
|
|
||
|
int main() {
|
||
|
int count;
|
||
|
cin >> count;
|
||
|
|
||
|
vector<snake> snakes;
|
||
|
int t;
|
||
|
cin >> t;
|
||
|
for (int i = 0; i < t; i++) {
|
||
|
int a;
|
||
|
cin >> a;
|
||
|
snakes.emplace_back(i + 1, a);
|
||
|
}
|
||
|
|
||
|
eat(snakes);
|
||
|
cout << snakes.size() << endl;
|
||
|
|
||
|
for (int i = 0; i < count - 1; i++) {
|
||
|
int n;
|
||
|
cin >> n;
|
||
|
sort(snakes.begin(), snakes.end(), sort_by_id);
|
||
|
#if defined(ENABLE_LOG)
|
||
|
printf("alter log: \n");
|
||
|
for (const auto &item: snakes) {
|
||
|
printf("%d ", item.id);
|
||
|
}
|
||
|
printf("\n");
|
||
|
#endif
|
||
|
for (int j = 0; j < n; j++) {
|
||
|
int id, alter;
|
||
|
cin >> id >> alter;
|
||
|
if (snakes.size() < id) {
|
||
|
// Respawn
|
||
|
snakes.emplace_back(id, alter);
|
||
|
} else {
|
||
|
// Alter power
|
||
|
snakes[id - 1].power = alter;
|
||
|
}
|
||
|
}
|
||
|
eat(snakes);
|
||
|
cout << snakes.size() << endl;
|
||
|
}
|
||
|
}
|