[CF1260D] A Game with Traps
首先,假设带 \(p\) 个人可以,那么带更少的人一定可以。
那么,可以二分带多少个人。
设当前二分带 \(x\) 个人。
带敏捷值最大的 \(x\) 个士兵肯定最好。
先去除当前无用的陷阱,即 \(d_i\) 小于等于 \(x\) 个士兵中的最小敏捷值。
陷阱区间不相交时
然后就是自己从 \(l_i\) 走到 \(r_i\) 解除这个陷阱,再走回来
陷阱区间相交时
看一看下面这个。

肯定不会从一个一个地从每个区间左边走到右边。
而是从第一个区间左边一直走到第二个区间右边。
写的时候直接左右端点差分,加贡献时对 \(2\) 取个 \(\min\)(往返总共走 \(2\) 次)。
#include <bits/stdc++.h>
#define int long long
#define mid (l + r >> 1)
using namespace std;
inline int read()
{
    int f = 0, ans = 0;
    char c = getchar();
    while (!isdigit(c))
        f |= c == '-', c = getchar();
    while (isdigit(c))
        ans = (ans << 3) + (ans << 1) + c - 48, c = getchar();
    return f ? -ans : ans;
}
void write(int x)
{
    if (x < 0)
        putchar('-'), x = -x;
    if (x > 9)
        write(x / 10);
    putchar(x % 10 + '0');
}
constexpr int N = 2e5 + 5, inf = 1e18;
int m, n, k, t, a[N];
int adj[N];
struct trap
{
    int l, r, d;
} b[N];
inline bool check(int x)
{
    int mn = a[x], ti = n + 1;
    for (int i = 1; i <= k; ++i)
        if (mn < b[i].d)
            adj[b[i].l] += 2, adj[b[i].r + 1] -= 2;
    for (int i = 1; i <= n; ++i)
        adj[i] += adj[i - 1], ti += min(adj[i], 2ll);
    for (int i = 1; i <= n; ++i)
        adj[i] = 0;
    return ti <= t;
}
signed main()
{
    // freopen(".in", "r", stdin);
    // freopen(".out", "w", stdout);
    m = read(), n = read(), k = read(), t = read();
    for (int i = 1; i <= m; ++i)
        a[i] = read();
    sort(a + 1, a + m + 1, greater<>());
    a[0] = inf;
    for (int i = 1; i <= k; ++i)
        b[i].l = read(), b[i].r = read(), b[i].d = read();
    int l = 0, r = m, it = -1;
    while (l <= r)
        check(mid)
            ? (it = mid, l = mid + 1)
            : (r = mid - 1);
    write(it);
    return 0;
}
 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号