昨晚 CF div2. D 思路求 hack
  • 板块学术版
  • 楼主Mr_罗
  • 当前回复5
  • 已保存回复5
  • 发布时间2024/9/28 08:30
  • 上次更新2024/9/28 11:10:57
查看原帖
昨晚 CF div2. D 思路求 hack
365751
Mr_罗楼主2024/9/28 08:30

赛时思路:

枚举 jj ,则只有 [jaj+1,j](j,j+aj1][j-a_j+1,j]\cup(j,j+a_j-1] 有可能到 jj 。用树状数组判掉。

考虑 ii 在所有点都能到的情况下不合法的情况,当且仅当存在两个位置 lirl\le i\le r ,使得 alrlarrla_l\le r-l\land a_r\le r-l

变形,得到 l+alrrarll+a_l\le r\land r-a_r\ge l 。显然要找最大的 rarr-a_r

l+alil+a_l\ge i ,那么应该在这个位置右侧判断,否则在 ii 右侧判断。前一种情况可以覆盖一个区间的 ii[l,l+al][l,l+a_l]),后一种情况只需要记录最小的 ll

代码:

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

#define CF

#define ll long long
#define ul unsigned ll
#define LL __int128_t
#define db double
#define DB long db
#define pii pair<int, int>
#define fi first
#define se second
#define mkpr make_pair
#define mem(a, x) memset(a, x, sizeof(a))
#define rep(i, l, r) for (int i(l), i##End(r); i <= i##End; i = -~i)
#define per(i, r, l) for (int i(r), i##End(l); i >= i##End; i = ~-i)

template<typename T, typename U> void chkmx(T &_a, U _b) { if (_a < _b) _a = _b; }
template<typename T, typename U> void chkmn(T &_a, U _b) { if (_a > _b) _a = _b; }

constexpr int N = 200005;
constexpr ll mod = 998244353;
int n, p, ans;
int a[N];
set<pii> S;
int mx[N];

struct BITree
{
    int s[N];
    void modify(int p, int k) { for (; p <= n; p += p & -p) s[p] += k; }
    int query(int p) { int res = 0; for (; p; p -= p & -p) res += s[p]; return res; }
} T;

void solve()
{
    S.clear(); rep(i, 1, n) T.s[i] = 0;
    scanf("%d", &n);
    rep(i, 1, n) scanf("%d", &a[i]);
    rep(j, 1, n)
    {
        if (j - a[j] + 1 <= j) T.modify(max(j - a[j] + 1, 1), 1), T.modify(j + 1, -1);
        if (j < a[j] + j - 1) T.modify(j + 1, 1), T.modify(min(a[j] + j, n + 1), -1);
    }
    mx[n] = n - a[n]; per(i, n - 1, 1) mx[i] = max(mx[i + 1], i - a[i]);
    p = n + 1, ans = 0; rep(i, 1, n)
    {
        if (T.query(i) == n && mx[i] < p) ans++;
        if (mx[i + a[i]] >= i) T.modify(i, -1), T.modify(i + a[i] + 1, 1);
        S.emplace(i + a[i], i);
        while (!S.empty() && S.begin()->fi < i) chkmn(p, S.begin()->se), S.erase(S.begin());
        // #ifndef ONLINE_JUDGE
        // printf("%d: %d %d %d\n", i, p, T.query(i), mx[i]);
        // for (auto [x, y] : S) printf(" - [%d %d]\n", x, y);
        // #endif
    }
    printf("%d\n", ans);
}

void init(){}

int main()
{
    init();
    #ifdef CF
    int _; scanf("%d", &_);
    while (_--) solve();
    #else
    solve();
    #endif
    return 0;
}
2024/9/28 08:30
加载中...