提交记录 53161


用户 题目 状态 得分 用时 内存 语言 代码长度
saffah_dsh_v41_0919 noi17b. 【NOI2017】蚯蚓排队 Accepted 100 550.981 ms 212828 KB C++17 8.05 KB
提交时间 评测时间
2026-09-19 18:38:04 2026-09-19 18:38:15
// noi17b 【NOI2017】蚯蚓排队
// Maintain counts of every length-k window (k <= Kmax over queries) in a hash
// table keyed by (64-bit rolling hash, k).  Merges/splits only change windows
// crossing the junction: walk back/forward up to Kmax-1 worms and rebuild them.
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
typedef unsigned long long u64;
typedef unsigned int u32;

static const u64 MODP = 998244353ULL;
#define MAXN 200005

// ---------------- I/O ----------------
static char *inbuf;
static size_t inpos;
static inline int gc() { return (unsigned char)inbuf[inpos++]; }

static char obuf[1 << 25];
static size_t olen = 0;
static inline void wnum(u64 x) {
    char t[24];
    int k = 0;
    if (!x) t[k++] = '0';
    while (x) { t[k++] = (char)('0' + x % 10); x /= 10; }
    while (k) obuf[olen++] = t[--k];
    obuf[olen++] = '\n';
}

// ---------------- hash table ----------------
static u64 *hkey;
static u32 *hval;
static u32 hmask;
static inline u32 *slot(u64 key) {
    if (!key) key = 0x9E3779B97F4A7C15ULL;
    u32 i = (u32)((key * 0x9E3779B97F4A7C15ULL) >> 40) & hmask;
    while (hkey[i] != 0 && hkey[i] != key) i = (i + 1) & hmask;
    if (hkey[i] == 0) { hkey[i] = key; hval[i] = 0; }
    return &hval[i];
}

static int n, m;
static unsigned char len_[MAXN];
static u32 prv[MAXN], nxt[MAXN];
static u64 pw[64];
static u64 base_;
static int K;

// left[i] = hash of the string len_[L[i]]..len_[L[i-1]] as a forward string
static u64 Lh[64];
static u64 Rh[64];
static unsigned char Lc[64], Rc[64];

static inline void addWindow(int k, u64 h, int delta) {
    u32 *c = slot((h << 6) | (u64)k);
    *c += delta;
}

int main() {
    inbuf = (char *)malloc(1 << 26);
    size_t got = fread(inbuf, 1, 1 << 26, stdin);
    (void)got;
    // ---- parse n, m ----
    while (inbuf[inpos] < '0' || inbuf[inpos] > '9') inpos++;
    { u64 x = 0; while (inbuf[inpos] >= '0' && inbuf[inpos] <= '9') { x = x * 10 + (inbuf[inpos] - '0'); inpos++; } n = (int)x; }
    while (inbuf[inpos] < '0' || inbuf[inpos] > '9') inpos++;
    { u64 x = 0; while (inbuf[inpos] >= '0' && inbuf[inpos] <= '9') { x = x * 10 + (inbuf[inpos] - '0'); inpos++; } m = (int)x; }
    {
        u64 x;
        for (int i = 1; i <= n; i++) {
            while (inbuf[inpos] < '0' || inbuf[inpos] > '9') inpos++;
            x = 0; while (inbuf[inpos] >= '0' && inbuf[inpos] <= '9') { x = x * 10 + (inbuf[inpos] - '0'); inpos++; }
            len_[i] = (unsigned char)x;
        }
    }
    // ---- first pass: find K = max k over queries, and count windows to size the table ----
    K = 1;
    {
        size_t save = inpos;
        for (int q = 0; q < m; q++) {
            while (inbuf[inpos] == '\n' || inbuf[inpos] == ' ' || inbuf[inpos] == '\r') inpos++;
            int op = inbuf[inpos] - '0';
            inpos++;
            if (op == 3) {
                while (inbuf[inpos] == ' ') inpos++;      // skip spaces
                {
                    char *sp2 = (char *)memchr(inbuf + inpos, ' ', 64 * 1024 * 1024 - inpos);
                    inpos = (size_t)(sp2 - inbuf);
                }
                while (inbuf[inpos] == ' ') inpos++;
                u64 x = 0; while (inbuf[inpos] >= '0' && inbuf[inpos] <= '9') { x = x * 10 + (inbuf[inpos] - '0'); inpos++; }
                if ((int)x > K) K = (int)x;
            } else if (op == 1) {
                while (inbuf[inpos] != '\n' && inbuf[inpos] != 0) inpos++;
            } else {
                while (inbuf[inpos] != '\n' && inbuf[inpos] != 0) inpos++;
            }
        }
        inpos = save;
    }
    if (K > 50) K = 50;
    // table size: at most n*(K) live windows + churn; use 2^22
    {
        u32 sz = 1u << 22;
        while ((u64)sz * 3 < (u64)n * (K + 1) * 4 && sz < (1u << 26)) sz <<= 1;
        hkey = (u64 *)calloc(sz, sizeof(u64));
        hval = (u32 *)calloc(sz, sizeof(u32));
        hmask = sz - 1;
        if (!hkey || !hval) return 1;
    }
    base_ = 1000003ULL;
    pw[0] = 1;
    for (int i = 1; i <= K + 2; i++) pw[i] = pw[i - 1] * base_;
    // ---- init: each worm alone -> windows of length 1 ----
    for (int i = 1; i <= n; i++) {
        prv[i] = 0; nxt[i] = 0;
        addWindow(1, (u64)len_[i], 1);
    }
    // ---- process operations ----
    for (int q = 0; q < m; q++) {
        while (inbuf[inpos] == '\n' || inbuf[inpos] == ' ' || inbuf[inpos] == '\r') inpos++;
        int op = inbuf[inpos] - '0';
        inpos++;
        if (op == 1) {
            while (inbuf[inpos] < '0' || inbuf[inpos] > '9') inpos++;
            u64 x = 0; while (inbuf[inpos] >= '0' && inbuf[inpos] <= '9') { x = x * 10 + (inbuf[inpos] - '0'); inpos++; }
            int i = (int)x;
            while (inbuf[inpos] < '0' || inbuf[inpos] > '9') inpos++;
            x = 0; while (inbuf[inpos] >= '0' && inbuf[inpos] <= '9') { x = x * 10 + (inbuf[inpos] - '0'); inpos++; }
            int j = (int)x;
            // collect up to K-1 worms ending at i (walk back)
            int nl = 0; {
                int p = i;
                while (p && nl < K) { Lc[nl++] = len_[p]; p = prv[p]; }
            }
            // Lh[a] = hash of Lc[a-1..0] read forward (i.e. the a worms ending at i)
            Lh[0] = 0;
            for (int a = 1; a <= nl; a++) Lh[a] = Lh[a - 1] + (u64)Lc[a - 1] * pw[a - 1];
            int nr = 0; {
                int p = j;
                while (p && nr < K) { Rc[nr++] = len_[p]; p = nxt[p]; }
            }
            Rh[0] = 0;
            for (int b = 1; b <= nr; b++) Rh[b] = Rh[b - 1] * base_ + Rc[b - 1];
            for (int a = 1; a <= nl; a++) {
                int bmax = K - a;
                if (bmax > nr) bmax = nr;
                for (int b = 1; b <= bmax; b++) addWindow(a + b, Lh[a] * pw[b] + Rh[b], 1);
            }
            nxt[i] = (u32)j; prv[j] = (u32)i;
        } else if (op == 2) {
            while (inbuf[inpos] < '0' || inbuf[inpos] > '9') inpos++;
            u64 x = 0; while (inbuf[inpos] >= '0' && inbuf[inpos] <= '9') { x = x * 10 + (inbuf[inpos] - '0'); inpos++; }
            int i = (int)x;
            int j = (int)nxt[i];
            if (j) {
                int nl = 0; {
                    int p = i;
                    while (p && nl < K) { Lc[nl++] = len_[p]; p = prv[p]; }
                }
                Lh[0] = 0;
                for (int a = 1; a <= nl; a++) Lh[a] = Lh[a - 1] + (u64)Lc[a - 1] * pw[a - 1];
                int nr = 0; {
                    int p = j;
                    while (p && nr < K) { Rc[nr++] = len_[p]; p = nxt[p]; }
                }
                Rh[0] = 0;
                for (int b = 1; b <= nr; b++) Rh[b] = Rh[b - 1] * base_ + Rc[b - 1];
                for (int a = 1; a <= nl; a++) {
                    int bmax = K - a;
                    if (bmax > nr) bmax = nr;
                    for (int b = 1; b <= bmax; b++) addWindow(a + b, Lh[a] * pw[b] + Rh[b], -1);
                }
                nxt[i] = 0; prv[j] = 0;
            }
        } else {
            // query: read s and k
            while (inbuf[inpos] == ' ') inpos++;
            int sp = (int)inpos;
            {
                char *sp2 = (char *)memchr(inbuf + inpos, ' ', 64 * 1024 * 1024 - inpos);
                inpos = (size_t)(sp2 - inbuf);
            }
            int slen = (int)(inpos - sp);
            inpos++;
            u64 x = 0; while (inbuf[inpos] >= '0' && inbuf[inpos] <= '9') { x = x * 10 + (inbuf[inpos] - '0'); inpos++; }
            int k = (int)x;
            const char *s = inbuf + sp;
            u64 ans = 1;
            if (slen >= k) {
                u64 h = 0;
                for (int t = 0; t < k; t++) h = h * base_ + (u64)(s[t] - '0');
                for (int t = 0; t + k <= slen; t++) {
                    if (t) h = (h - (u64)(s[t - 1] - '0') * pw[k - 1]) * base_ + (u64)(s[t + k - 1] - '0');
                    u64 key = (h << 6) | (u64)k;
                    u32 *c = slot(key);
                    ans = ans * (u64)(*c) % MODP;
                    if (!ans) break;
                }
            } else ans = 1;
            wnum(ans);
            if (olen > (1 << 25) - 64) { fwrite(obuf, 1, olen, stdout); olen = 0; }
        }
    }
    if (olen) fwrite(obuf, 1, olen, stdout);
    return 0;
}

CompilationN/AN/ACompile OKScore: N/A

Testcase #14.518 ms48 MB + 44 KBAcceptedScore: 4

Testcase #24.5 ms48 MB + 40 KBAcceptedScore: 4

Testcase #312.215 ms48 MB + 56 KBAcceptedScore: 4

Testcase #44.705 ms48 MB + 52 KBAcceptedScore: 4

Testcase #59.651 ms48 MB + 68 KBAcceptedScore: 4

Testcase #69.317 ms49 MB + 304 KBAcceptedScore: 4

Testcase #717.367 ms49 MB + 272 KBAcceptedScore: 4

Testcase #853.485 ms49 MB + 264 KBAcceptedScore: 4

Testcase #979.787 ms49 MB + 284 KBAcceptedScore: 4

Testcase #1099.562 ms51 MB + 912 KBAcceptedScore: 4

Testcase #11159.109 ms51 MB + 936 KBAcceptedScore: 4

Testcase #1215.194 ms50 MB + 552 KBAcceptedScore: 4

Testcase #1336.269 ms98 MB + 528 KBAcceptedScore: 4

Testcase #14120.676 ms98 MB + 520 KBAcceptedScore: 4

Testcase #15142.741 ms98 MB + 540 KBAcceptedScore: 4

Testcase #16220.782 ms103 MB + 812 KBAcceptedScore: 4

Testcase #17287.803 ms103 MB + 832 KBAcceptedScore: 4

Testcase #1872.17 ms67 MB + 208 KBAcceptedScore: 4

Testcase #1972.301 ms67 MB + 236 KBAcceptedScore: 4

Testcase #2029.379 ms53 MB + 144 KBAcceptedScore: 4

Testcase #2176.219 ms197 MB + 192 KBAcceptedScore: 4

Testcase #22272.436 ms197 MB + 180 KBAcceptedScore: 4

Testcase #23289.211 ms197 MB + 204 KBAcceptedScore: 4

Testcase #24481.612 ms207 MB + 840 KBAcceptedScore: 4

Testcase #25550.981 ms207 MB + 860 KBAcceptedScore: 4


Judge Duck Online | 评测鸭在线
Server Time: 2026-11-08 11:57:00 | Loaded in 1 ms | Server Status
个人娱乐项目,仅供学习交流使用 | 捐赠