Loading

UNR #10 D1T3 补题记录

完全想不到倍增分块啊。

考虑一个 \((l, k)\) 的判定,我们取出最大的 \(b\) 满足 \(2^b \le k - l\),比较 \(s[l: l + 2^b - 1]\)\(s^R [k - 2 ^ b + 1, k]\) 即可得知 \(k\) 是否合法。

这样一次询问 \([l, r]\) 的求解分为了 \(b = 0, 1, \dots, b'\) 左端点为 \(l\) 的问题,最后一段可能不完整。

所有后缀和前缀一起排序,采用倍增的方法排序,可以得知每个长为 \(2 ^ b\) 的子串的排序结果。

然后排名的偏序用线段树维护,时间复杂度为 \(\mathcal O(n\log ^ 2n + q\log n)\)

点击查看代码
#include <bits/stdc++.h>
#define ll int
#define LL long long
#define pir pair <ll, ll>
#define fi first
#define se second
#define mkp make_pair
#define pb push_back
#define i128 __int128
#define uLL unsigned LL
#define For(i, a, b) for(ll i = a; i <= b; i++)
#define DFor(i, a, b) for(ll i = a; i >= b; i--)
#define debug(...) fprintf(stderr, __VA_ARGS__)
template <class T1, class T2> void chkmax(T1 &x, const T2 y) { x = x < y? y : x; }
template <class T1, class T2> void chkmin(T1 &x, const T2 y) { x = x < y? x : y; }
template <class T> void rd(T &x) {
    char ch; bool f = 0;
    while(!isdigit(ch = getchar()))
        if(ch == '-') f = 1;
    x = ch - '0';
    while(isdigit(ch = getchar()))
        x = (x << 1) + (x << 3) + ch - '0';
    if(f) x = -x;
}
const ll maxn = 4e5 + 10, M = 2e6 + 10, mod = 998244353;
template <class T1, class T2>
void add(T1 &x, const T2 y) { x = x + y >= mod? x + y - mod : x + y; }
template <class T1, class T2>
void sub(T1 &x, const T2 y) { x = x < y? x + mod - y : x - y; }
template <class T1, class T2>
ll pls(const T1 x, const T2 y) { return x + y >= mod? x + y - mod : x + y; }
template <class T1, class T2>
ll mus(const T1 x, const T2 y) { return x < y? x + mod - y : x - y; }
using namespace std;

ll _, n, q, _q, e, L[M], R[M], sa[maxn], rk[maxn], oldrk[maxn << 1], cnt[maxn], id[maxn];
char str[maxn];
uLL w, a[maxn], ans[M];

void report() {
    uLL ret = 0;
    // For(i, 1, q) debug("%llu\n", ans[i]);
    For(i, 1, q) ret ^= ans[i] + (uLL) i * i * i;
    printf("%llu\n", ret); exit(0);
}

vector <ll> vec[20], sec[maxn];
struct Data { uLL prod, sum; } res[maxn];
const Data operator + (const Data a, const Data b) {
    return (Data) {a.prod * b.prod, a.sum + b.sum * a.prod};
}

struct SGT {
    Data t[maxn << 2];
    void modify(ll p, ll l, ll r, ll x) {
        if(l == r) return t[p] = (Data) {w, a[l]}, void();
        ll mid = l + r >> 1;
        if(x <= mid) modify(p << 1, l, mid ,x);
        else modify(p << 1|1, mid + 1, r, x);
        t[p] = t[p << 1] + t[p << 1|1];
    }
    Data ask(ll p, ll l, ll r, ll ql, ll qr) {
        if(ql <= l && r <= qr) return t[p];
        if(qr < l || r < ql) return (Data) {1, 0};
        ll mid = l + r >> 1;
        return ask(p << 1, l, mid, ql, qr) + ask(p << 1|1, mid + 1, r, ql, qr);
    }
} tr;

int main() {
    rd(_), rd(n), rd(w), rd(q), rd(_q), rd(e), scanf("%s", str + 1);
    For(i, 1, n) rd(a[i]);
    mt19937 rng(e);
    auto rnd = [&](unsigned L, unsigned R) -> unsigned {
        uLL range = (uLL) R - L + 1;
        unsigned bucket = (1ull << 32) / range;
        uLL limit = bucket * range;
        uLL v;
        do {
            v = rng();
        } while((uLL) v >= limit);
        return L + (unsigned) ((uLL) v / bucket);
    };
    For(o, 1, q) {
        ll l, r;
        if(o <= _q) rd(l), rd(r);
        else {
            l = rnd(1, n), r = rnd(1, n);
            if(l > r) swap(l, r);
        }
        L[o] = l, R[o] = r;
        ll b = 0;
        while(l + (1 << b + 1) - 1 <= r) ++b;
        vec[b].pb(o);
    }
    str[n + 1] = 'a' - 1;
    For(i, 1, n) str[2 * n - i + 2] = str[i];
    ll m = 2 * n + 1;
    For(i, 1, m) ++cnt[str[i] - 'a' + 1];
    For(i, 1, 26) cnt[i] += cnt[i - 1];
    For(i, 1, m) sa[cnt[str[i] - 'a' + 1]--] = i;
    ll p = 0;
    For(i, 1, m)
        if(str[sa[i]] == str[sa[i - 1]]) rk[sa[i]] = p;
        else rk[sa[i]] = ++p;
    For(i, 1, n) res[i] = (Data) {w, 0};
    for(ll w = 1, u = 1; w < n; w <<= 1, ++u) {
        p = 0;
        For(i, 0, w - 1) id[++p] = m - i;
        For(i, 1, m)
            if(sa[i] > w) id[++p] = sa[i] - w;
        memset(cnt, 0, sizeof cnt);
        For(i, 1, m) oldrk[i] = rk[i], ++cnt[rk[i]];
        For(i, 1, m) cnt[i] += cnt[i - 1];
        DFor(i, m, 1) sa[cnt[rk[id[i]]]--] = id[i];
        p = 0;
        For(i, 1, m)
            if(oldrk[sa[i]] == oldrk[sa[i - 1]] &&
             oldrk[sa[i] + w] == oldrk[sa[i - 1] + w]) rk[sa[i]] = p, assert(sa[i] < sa[i - 1]);
            else rk[sa[i]] = ++p;
        for(ll i: vec[u]) sec[L[i]].pb(i);
        For(i, 1, 4 * n) tr.t[i] = (Data) {1, 0};
        DFor(i, 2 * n + 1, 1) {
            ll x = sa[i];
            if(x <= n) {
                for(ll j: sec[x]) {
                    assert(x + (1 << u) - 1 <= R[j] && R[j] <= x + (1 << u + 1) - 2);
                    ans[j] = (res[x] + tr.ask(1, 1, n, x + (1 << u) - 1, R[j])).sum;
                } sec[x].clear();
                if(x + (1 << u + 1) - 2 <= n)
                    res[x] = res[x] + tr.ask(1, 1, n, x + (1 << u) - 1, x + (1 << u + 1) - 2);
            } else {
                if(x == n + 1) continue;
                x = 2 * n + 2 - x;
                tr.modify(1, 1, n, x);
            }
        }
    }
    report();
    return 0;
}
posted @ 2026-07-11 17:05  Sktn0089  阅读(21)  评论(0)    收藏  举报