int N, M, type, n; int posi[MAXN][2]= {0}; // n: 边化点 int ans = 0;
int father[MAXN]= {0}, son[MAXN][2]= {0}; int rev[MAXN]= {0}; int vimi[MAXN]= {0}, fic[MAXN]= {0}, vism[MAXN]= {0}; // 当前节点连的非树节点个数、当前节点虚子树vimi和、当前节点虚实子树vimi和 int mini[MAXN]= {0}; // 最早入队边 intisroot(int p){ return son[father[p]][0] != p && son[father[p]][1] != p; } intsonbel(int p){ return son[father[p]][1] == p; } voidreverse(int p){ if (! p) return ; swap (son[p][0], son[p][1]); rev[p] ^= 1; } voidpushup(int p){ vism[p] = vimi[p] + fic[p] + vism[son[p][0]] + vism[son[p][1]]; mini[p] = min (p <= N ? INF : p, min (mini[son[p][0]], mini[son[p][1]])); } voidpushdown(int p){ if (! rev[p]) return ; reverse (son[p][0]), reverse (son[p][1]); rev[p] = 0; } voidrotate(int p){ int fa = father[p], anc = father[fa]; int s = sonbel (p); son[fa][s] = son[p][s ^ 1]; if (son[fa][s]) father[son[fa][s]] = fa; if (! isroot (fa)) son[anc][sonbel (fa)] = p; father[p] = anc; son[p][s ^ 1] = fa, father[fa] = p; pushup (fa), pushup (p); } intstack[MAXN], top; voidsplay(int p){ top = 0; stack[++ top] = p; for (int tp = p; ! isroot (tp); tp = father[tp]) stack[++ top] = father[tp]; while (top > 0) pushdown (stack[top]), top --; for (int fa = father[p]; ! isroot (p); rotate (p), fa = father[p]) if (! isroot (fa)) sonbel (p) == sonbel (fa) ? rotate (fa) : rotate (p); } voidaccess(int p){ for (int tp = 0; p; tp = p, p = father[p]) { splay (p); fic[p] += vism[son[p][1]] - vism[tp]; son[p][1] = tp; pushup (p); } } voidmakeroot(int p){ access (p), splay (p); reverse (p); } intfindroot(int p){ access (p), splay (p); while (son[p][0]) { pushdown (p); p = son[p][0]; } splay (p); return p; } inlineintvalue(int p){ return vism[p] > 0; } // 判断是否成环,若成环则答案需要再点个数上加一 voidhideit(int p, int delta){ // 将树上边变为使成环边 makeroot (p); ans -= value (p); vimi[p] += delta, pushup (p); ans += value (p); } bool in[MAXN]= {false}; voidlink(int id, int x, int y){ makeroot (x), makeroot (y); ans -= value (x) + value (y); // 删去原来两个分开的连通块的贡献再加上新合成连通块贡献 ans ++; father[x] = father[y] = id; fic[id] += vism[x] + vism[y], pushup (id); ans += value (id); in[id] = true; } voidcut(int id, int x, int y){ makeroot (x), access (y), splay (id); ans --, ans -= value (id); father[x] = father[y] = 0; ans += value (x) + value (y); in[id] = false; } voidPUSH(int id, int x, int y){ if (x == y) { hideit (x, 2); return ; } makeroot (x); if (findroot (y) == x) { access (y), splay (y); int p = mini[y]; cut (p, posi[p][0], posi[p][1]); hideit (posi[p][0], 1), hideit (posi[p][1], 1); } link (id, x, y); } voidPOP(int id, int x, int y){ if (! in[id]) { hideit (x, - 1), hideit (y, - 1); return ; } cut (id, x, y); }
inlineintgetnum(){ int num = 0; char ch = getchar (); while (! isdigit (ch)) ch = getchar (); while (isdigit (ch)) num = (num << 3) + (num << 1) + ch - '0', ch = getchar (); return num; }
intmain(){ n = N = getnum (), M = getnum (), type = getnum (); int st = N + 1; mini[0] = INF; for (int i = 1; i <= M; i ++) { int op, a, b; if (type == 0) { op = getnum (); if (op == 1) a = getnum (), b = getnum (); } else { op = (getnum () + ans) % 2; if (op == 1) a = (getnum () + ans) % N + 1, b = (getnum () + ans) % N + 1; } if (op == 1) { posi[++ n][0] = a, posi[n][1] = b; // ++ n表示边化点 PUSH (n, a, b); } else { POP (st, posi[st][0], posi[st][1]); st ++; } printf ("%d\n", ans); }
int m = 0; int father[MAXN]= {0}; int tr[MAXN][26]= {0}, fail[MAXN]= {0}; LL value[MAXN]= {0}; voidinsert(int x){ int p = 0; int n = strlen (str + 1); for (int i = 1; i <= n; i ++) { int c = str[i] - 'a'; if (! tr[p][c]) { tr[p][c] = ++ m; father[m] = p; } p = tr[p][c]; } value[p] += x; } queue<int> que; LL f[MAXN]= {0}, g[MAXN]= {0}, h[MAXN]= {0}; voidbuild(){ for (int i = 0; i < 26; i ++) if (tr[0][i]) que.push(tr[0][i]); while (! que.empty()) { int u = que.front(); que.pop(); value[u] += value[fail[u]]; g[u] = g[father[u]] + value[u]; if (! fail[u]) h[u] = h[father[u]]; else { h[u] = - INF; for (int j = father[u]; j != father[fail[u]]; j = fail[j]) h[u] = max (h[u], h[j] + value[fail[u]]); } f[u] = max (f[fail[u]], max (g[u], h[u])); for (int i = 0; i < 26; i ++) { if (tr[u][i]) { fail[tr[u][i]] = tr[fail[u]][i]; que.push(tr[u][i]); } else tr[u][i] = tr[fail[u]][i]; } } } LL solve(){ LL ans = 0; int p = 0, n = strlen (str + 1); for (int i = 1; i <= n; i ++) { int c = str[i] - 'a'; p = tr[p][c]; ans = max (ans, f[p]); } return ans; }
inlineintgetnum(){ int num = 0; char ch = getchar (); bool isneg = false; while (! isdigit (ch)) { if (ch == '-') isneg = true; ch = getchar (); } while (isdigit (ch)) num = (num << 3) + (num << 1) + ch - '0', ch = getchar (); return isneg ? - num : num; }
intmain(){ N = getnum (), M = getnum (); for (int i = 1; i <= N; i ++) { scanf ("%s", str + 1); insert (getnum ()); } scanf ("%s", str + 1); insert (0); build (); cout << solve () << endl;