CF1591F Non-equal Neighbours

呆呆题,提供一种十分呆呆的做法。

我们先暴力 DP,令 $dp_{i,j}$ 表示当前填数到第 $i$ 位,第 $i$ 位填了 $j$ 的方案数,那么转移即为 $dp_{i,j}=\sum\limits_{k\not=j}dp_{i-1,k}(1\le j\le a_i)$,这个转移就相当于是你需要维护一个序列 $b$,每次将 $1\le j\le a_i$ 的 $b_j$ 变为 $sum-b_j$($sum$ 为 $b$ 序列的和),将 $j\ge a_i$ 的 $b_j$ 变为 $0$,这个就相当于维护区间乘 $-1$ 和 $0$,区间加 $sum$,查询全局和,就是线段树2,然后就做完了,复杂度 $\mathcal{O}(n\log val)$,$val$ 是值域。

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5, mod = 998244353;
int n, ls[N * 60], rs[N * 60], tr[N * 60], tag1[N * 60], tag2[N * 60], rt, a[N], cnt;
int NewNode() {tag2[++cnt] = 1; return cnt;}
void pd1(int p, int l, int r) {
    if (tag1[p]) {
        int mid = l + r >> 1;
        if (!ls[p]) ls[p] = NewNode();
        if (!rs[p]) rs[p] = NewNode();
        tr[ls[p]] = (tr[ls[p]] + 1ll * tag1[p] * (mid - l + 1)) % mod;
        tr[rs[p]] = (tr[rs[p]] + 1ll * tag1[p] * (r - mid)) % mod;
        tag1[ls[p]] = (tag1[ls[p]] + tag1[p]) % mod;
        tag1[rs[p]] = (tag1[rs[p]] + tag1[p]) % mod;
        tag1[p] = 0;
    }
}
void pd2(int p) {
    if (tag2[p] != 1) {
        if (!ls[p]) ls[p] = NewNode();
        if (!rs[p]) rs[p] = NewNode();
        tr[ls[p]] = 1ll * tr[ls[p]] * tag2[p] % mod;
        tr[rs[p]] = 1ll * tr[rs[p]] * tag2[p] % mod;
        tag2[ls[p]] = 1ll * tag2[ls[p]] * tag2[p] % mod;
        tag2[rs[p]] = 1ll * tag2[rs[p]] * tag2[p] % mod;
        tag1[ls[p]] = 1ll * tag1[ls[p]] * tag2[p] % mod;
        tag1[rs[p]] = 1ll * tag1[rs[p]] * tag2[p] % mod;
        tag2[p] = 1;
    }
}
void push_up(int p) {tr[p] = (tr[ls[p]] + tr[rs[p]]) % mod;}
void modify(int &p, int l, int r, int x, int y, int z, int op) {
    if (x > y) return;
    if (!p) p = NewNode();
    if (l >= x && r <= y) {
        if (op == 1) {
            tr[p] = (tr[p] + 1ll * z * (r - l + 1)) % mod;
            if (l != r) pd2(p), pd1(p, l, r);
            tag1[p] = (tag1[p] + z) % mod;
        } else {
            tr[p] = 1ll * z * tr[p] % mod;
            if (l != r) pd2(p), pd1(p, l, r);
            tag2[p] = 1ll * tag2[p] * z % mod;
        }
        return;
    }
    pd2(p); pd1(p, l, r); int mid = l + r >> 1;
    if (mid >= x) modify(ls[p], l, mid, x, y, z, op);
    if (mid < y) modify(rs[p], mid + 1, r, x, y, z, op);
    push_up(p);
}

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
    modify(rt, 1, 1e9, 1, a[1], 1, 1);
    for (int i = 2; i <= n; i++) {
        int sum = tr[rt];
        modify(rt, 1, 1e9, 1, a[i], -1, 2);
        modify(rt, 1, 1e9, 1, a[i], sum, 1);
        modify(rt, 1, 1e9, a[i] + 1, 1e9, 0, 2);
    }
    printf("%d\n", (tr[rt] + mod) % mod);
    return 0;
}

 

posted @ 2022-03-27 19:46  Dzhao_qwq  阅读(45)  评论(0)    收藏  举报