CodeForces Educational Codeforces Round 161 (Rated for Div. 2) D.Berserk Monsters 难度1900

题目:

Monocarp 正在玩电脑游戏(又一次)。猜猜他在做什么?没错,杀怪。

一排有 n个怪物,编号从 1 到 n 。其中 i号 个怪物有两个参数:攻击值等于 ai,防御值等于 di 。为了杀死这些怪物,莫诺卡普给它们施放了狂暴咒语,因此它们会互相攻击,而不是攻击莫诺卡普的角色。

战斗由 n个回合组成。每回合都会发生以下情况:

  • 首先,每个 i活着的怪物都会对左边最近的活着的怪物(如果存在)和右边最近的活着的怪物(如果存在)造成 ai 伤害;
  • 然后,每个在本回合中受到超过 dj 伤害的活着的怪物 j 死亡。也就是说,当且仅当 j 怪物的防御值 dj 严格小于它在本轮受到的总伤害时,它才会死亡。

计算每一轮中死亡的怪物数量。

输入:

第一行包含一个整数 t ( 1 ≤ t ≤ 10^4) - 测试用例数。

每个测试用例由三行组成:

  • 第一行包含一个整数 n ( 1≤n≤3?10^5 );
  • 第二行包含 n 个整数 a1,a2,…,an1,2,…, ( 1≤ai≤10^9 )( 1≤ai≤10^9 );
  • 第三行包含 n 个整数 d1,d2,…,dn1,2,…, ( 1≤di≤109 )。

输入的附加限制:所有测试用例的 n 之和不超过 3?10^5。

输出:

对于每个测试案例,打印 n 个整数。 i 个整数应该等于在 i 个回合中死亡的怪物数量。

样例1

3
5
3 4 7 5 10
4 9 1 18 1
2
2 1
1 3
4
1 1 2 4
3 3 4 2
3 1 0 0 0 
0 0 
1 1 1 0 

思路:

首先思考一个怪物在什么情况下会死亡呢

两种情况

  1. 一开始的时候就被周围的怪物弄死了
  2. 剩下的就是第一回和没死的,假设上一回和没死的怪物,周围的怪都没死,那么他受的伤害和上一回和相同,依旧可以存活,也就是说只有上一回合旁边的怪物死了,才有可能死亡。

解决办法:

  • 对于第一种情况,只能进行预处理
  • 对于第二种情况,那就是记录上一回合死亡的怪物然后再出来与他相邻的怪物

怎么快速获取死亡怪物附近的两个怪物呢,可以记录左右节点,利用数组存储,实现复杂,对于连续死多个处理麻烦,利用链表,又无法快速获取下标。

使用stl容器的set,利用其中的upper_bound快速找到他的下一个位置的怪物,那么怎么找前一个呢,利用greater<int>将set反序,由于upper_bound找到的是等于自己的下一个元素,那么对于反序的就是小于自己的第一个元素,也就是前一个坐标,然后判断是否存在,在利用左右两边怪物的攻击判断是否能够击杀,能就用队列现存下来,然后再在set当中删除他的下标,再循环此操作

#include<bits/stdc++.h>
using namespace std;

#define x first
#define y second 
#define Yes cout << "Yes
"
#define No cout << "No
"
#define YES cout << "YES
"
#define NO cout << "NO
"
#define ls u << 1
#define rs u << 1 | 1
#define all(x) x.begin(),x.end()
// #define int long long
#define i128 __int128

inline int gcd(int a, int b) {return b > 0 ? gcd(b, a % b) : a;}
inline int lowbit(int x) {return x & (-x);}
int qmi(int a, int b, int mod){int res = 1;while(b) {if(b & 1) res = res * a % mod;a = a * a % mod;b >>= 1;}return res;}
inline i128 read(){i128 x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-')f = -1;ch = getchar();}while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}return x * f;}
inline void print(i128 x){if(x < 0){putchar('-');x = -x;}if(x > 9)print(x / 10);putchar(x % 10 + '0');}

typedef long long ll;
typedef pair<int, int> PII;
typedef pair<PII, int> PIII;
const int N = 1e5 + 10, inf = 0x3f3f3f3f, mod = 1e9 + 7;

/*
int mp[N + 1];
vector<int>prim;
void primes() {
    for (int i = 2; i <= N; i++) {
        if (!mp[i]) {
            mp[i] = i;
            prim.push_back(i);
        }
        
        for (auto p : prim) {
            if (i * p > N) break;
            mp[i * p] = p;
            if (i % p == 0) break;
        }
    }
}
*/

/*
int fact[N], infact[N]; // 组合数
int C(int a, int b) {return fact[a] * infact[b] % mod * infact[a - b] % mod;} 
void combination() {fact[0] = infact[0] = 1;for(int i = 1; i < N; i ++) {fact[i] = fact[i - 1] * i % mod;infact[i] = fact[i] * qmi(i, mod - 2, mod) % mod;}}
*/

void solve()
{
    int n; cin >> n;
    vector<int>a(n + 1, 0), d(n + 1, 0);
    set<int>stx;
    set<int, greater<int>>sti;
    for(int i = 1; i <= n; i ++) cin >> a[i];
    for(int i = 1; i <= n; i ++) cin >> d[i], stx.insert(i), sti.insert(i);
    
    vector<int>c(n + 2, 0);
    for(int j = 1; j <= n; j ++) {
        c[j - 1] += a[j], c[j + 1] += a[j];
    }
    
    set<int>s;
    for(int i = 1; i <= n; i ++) if(c[i] > d[i]) s.insert(i), stx.erase(i), sti.erase(i);
    
    vector<bool>stb(n + 1, 0);
    for(int j = 1; j <= n; j ++) {
        cout << s.size() << ' ';
        vector<int>v;
        for(auto t : s) {
            auto itx = stx.upper_bound(t);
            int ans = 0;
            if(itx != stx.end()) {
                int p = *itx;
                auto itxx = stx.upper_bound(p);
                auto itxi = sti.upper_bound(p);
                if(itxx != stx.end()) ans += a[*itxx];
                if(itxi != sti.end()) ans += a[*itxi];
                if(ans > d
) v.push_back(p); } auto iti = sti.upper_bound(t); ans = 0; if(iti != sti.end()) { int p = *iti; auto itix = stx.upper_bound(p); auto itii = sti.upper_bound(p); if(itix != stx.end()) ans += a[*itix]; if(itii != sti.end()) ans += a[*itii]; if(ans > d
) v.push_back(p); } } s.clear(); for(auto k : v) s.insert(k), stx.erase(k), sti.erase(k); } cout << ' '; } signed main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t = 1; cin >> t; while (t--) { solve(); } }