@ljt12138
2018-11-17T11:13:11.000000Z
字数 24722
阅读 837
这是一些luogu/loj/bzoj模板题的代码...
注意更新pre...
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 10005;
int n, m, blk;
struct node {
int l, r, id, ans;
friend bool operator < (const node &a, const node &b)
{
if (a.l/blk == b.l/blk && a.r/blk == b.r/blk) return a.id < b.id;
if (a.l/blk == b.l/blk) return a.r < b.r;
return a.l < b.l;
}
} qy[MAXN];
int qtop = 0;
inline bool cmp(const node &a, const node &b)
{ return a.id < b.id; }
int a[MAXN];
int T[MAXN*100];
int pos[MAXN], dt[MAXN], id[MAXN], pre[MAXN], mtop = 0, top = 0;
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
blk = pow(n, 2.0/3.0);
for (int i = 1; i <= m; i++) {
char c;
int aa, b;
scanf("\n%c %d%d", &c, &aa, &b);
if (c == 'Q') qy[++qtop] = (node){aa, b, i, 0};
else pos[++mtop] = aa, pre[mtop] = a[aa], dt[mtop] = b, id[mtop] = i;
}
sort(qy+1, qy+qtop+1);
int L = 1, R = 0, Ans = 0;
memset(T, 0, sizeof T);
for (int i = 1; i <= qtop; i++) {
while (R < qy[i].r) R++, T[a[R]]++, Ans += (T[a[R]] == 1);
while (L > qy[i].l) L--, T[a[L]]++, Ans += (T[a[L]] == 1);
while (L < qy[i].l) T[a[L]]--, Ans -= (T[a[L]] == 0), L++;
while (R > qy[i].r) T[a[R]]--, Ans -= (T[a[R]] == 0), R--;
while (top+1 <= mtop && id[top+1] <= qy[i].id) {
top++;
if (a[pos[top]] != dt[top]) {
pre[top] = a[pos[top]];
if (pos[top] >= L && pos[top] <= R) {
T[a[pos[top]]]--, T[dt[top]]++;
Ans -= (T[a[pos[top]]] == 0), Ans += (T[dt[top]] == 1);
}
a[pos[top]] = dt[top];
}
}
while (id[top] > qy[i].id) {
if (a[pos[top]] != pre[top]) {
if (pos[top] >= L && pos[top] <= R) {
T[a[pos[top]]]--, T[pre[top]]++;
Ans -= (T[a[pos[top]]] == 0), Ans += (T[pre[top]] == 1);
}
a[pos[top]] = pre[top];
}
top--;
}
qy[i].ans = Ans;
}
sort(qy+1, qy+qtop+1, cmp);
for (int i = 1; i <= qtop; i++)
printf("%d\n", qy[i].ans);
return 0;
}
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 200005;
const int mod = 998244353, g = 3;
int A[MAXN], B[MAXN], C[MAXN];
int n, m;
int rev[MAXN];
int power(int a, int n)
{
int ans = 1;
for (int i = 0; i <= 30; i++) {
if (n&(1<<i)) ans = (long long)ans*a%mod;
a = (long long)a*a%mod;
}
return ans;
}
inline int inv(int n)
{ return power(n, mod-2); }
void NTT(int A[], int n, int flag)
{
int lgn = int(log2(n)+0.1);
rev[0] = 0;
for (int i = 1; i < n; i++) rev[i] = (rev[i>>1]>>1)|((i&1)<<(lgn-1));
for (int i = 0; i < n; i++)
if (rev[i] < i)
swap(A[i], A[rev[i]]);
for (int k = 2; k <= n; k <<= 1) {
int dw = power(g, (mod-1)/k);
if (flag == -1) dw = inv(dw);
for (int i = 0; i < n; i += k) {
int w = 1, u, t;
for (int j = 0; j < k>>1; j++) {
u = A[i+j], t = (long long)w*A[i+j+(k>>1)]%mod;
A[i+j] = (u+t)%mod, A[i+j+(k>>1)] = ((u-t)%mod+mod)%mod;
w = (long long)w*dw%mod;
}
}
}
if (flag == -1) {
int invn = inv(n);
for (int i = 0; i < n; i++)
A[i] = (long long)A[i]*invn%mod;
}
}
char str[MAXN];
int main()
{
scanf("%d", &n);
scanf("%s", str);
for (int i = 0; i < n; i++) A[i] = str[n-i-1]-'0';
scanf("%s", str);
for (int i = 0; i < n; i++) B[i] = str[n-i-1]-'0';
int m = 1;
while (m < n*2) m <<= 1;
NTT(A, m, 1), NTT(B, m, 1);
for (int i = 0; i < m; i++) C[i] = (long long)A[i]*B[i]%mod;
NTT(C, m, -1);
for (int i = 0; i < m-1; i++) {
C[i+1] += C[i]/10;
C[i] %= 10;
}
int k = m-1;
while (C[k] == 0) k--;
for (int i = k; i >= 0; i--)
printf("%d", C[i]);
puts("");
return 0;
}
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 20005;
struct node {
int to, next, dis;
} edge[MAXN*2];
int head[MAXN], top = 0;
inline void push(int i, int j, int d)
{ edge[++top] = (node) {j, head[i], d}, head[i] = top; }
int vis[MAXN], siz[MAXN];
int num[3];
long long ans = 0;
int n;
void dfs_siz(int nd, int f)
{
siz[nd] = 1;
for (int i = head[nd]; i; i = edge[i].next) {
int to = edge[i].to;
if (to == f || vis[to]) continue;
dfs_siz(to, nd), siz[nd] += siz[to];
}
}
void find_center(int nd, int f, const int tot_siz, int &cnt, int &ans)
{
int maxs = tot_siz-siz[nd];
for (int i = head[nd]; i; i = edge[i].next) {
int to = edge[i].to;
if (to == f || vis[to]) continue;
find_center(to, nd, tot_siz, cnt, ans);
maxs = max(maxs, siz[to]);
}
if (maxs < cnt) cnt = maxs, ans = nd;
}
void dfs_calc(int nd, int f, int dt)
{
ans += num[(3-dt)%3]*2;
for (int i = head[nd]; i; i = edge[i].next) {
int to = edge[i].to;
if (to == f || vis[to]) continue;
dfs_calc(to, nd, (dt+edge[i].dis)%3);
}
}
void dfs_paint(int nd, int f, int dt)
{
num[dt]++;
for (int i = head[nd]; i; i = edge[i].next) {
int to = edge[i].to;
if (to == f || vis[to]) continue;
dfs_paint(to, nd, (dt+edge[i].dis)%3);
}
}
void calc(int nd)
{
dfs_siz(nd, 0);
int cnt = INT_MAX, center = 0;
find_center(nd, 0, siz[nd], cnt, center);
vis[center] = 1, ans++, num[0]++;
for (int i = head[center]; i; i = edge[i].next) {
int to = edge[i].to, d = edge[i].dis;
if (vis[to]) continue;
dfs_calc(to, center, d%3);
dfs_paint(to, center, d%3);
}
num[0] = num[1] = num[2] = 0;
for (int i = head[center]; i; i = edge[i].next) {
int to = edge[i].to;
if (!vis[to]) calc(to);
}
}
inline long long gcd(long long a, long long b)
{ return b == 0 ? a : gcd(b, a%b); }
int main()
{
scanf("%d", &n);
for (int i = 1; i < n; i++) {
int u, v, d;
scanf("%d%d%d", &u, &v, &d);
push(u, v, d), push(v, u, d);
}
calc(1);
long long tot = (long long)n*n;
long long c = gcd(ans, tot);
cout << ans/c << "/" << tot/c << endl;
return 0;
}
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 500005;
struct node {
int to, next;
} edge[MAXN*2];
int head[MAXN], top = 0;
inline void push(int i, int j)
{ edge[++top] = (node) {j, head[i]}, head[i] = top; }
int n, m, S, u, v;
vector<pair<int,int> > vec[MAXN];
int fa[MAXN], vis[MAXN], ans[MAXN];
inline int findf(int nd)
{ return fa[nd]?fa[nd]=findf(fa[nd]):nd; }
void tarjan(int nd, int f)
{
vis[nd] = 1;
for (int i = 0; i < vec[nd].size(); i++) {
int to = vec[nd][i].first, id = vec[nd][i].second;
if (vis[to]) ans[id] = findf(to);
}
for (int i = head[nd]; i; i = edge[i].next) {
int to = edge[i].to;
if (to == f) continue;
tarjan(to, nd);
}
fa[nd] = f;
}
int main()
{
scanf("%d%d%d", &n, &m, &S);
for (int i = 1; i < n; i++) {
scanf("%d%d", &u, &v);
push(u, v), push(v, u);
}
for (int i = 1; i <= m; i++) {
scanf("%d%d", &u, &v);
vec[u].push_back(make_pair(v, i)), vec[v].push_back(make_pair(u, i));
}
tarjan(S, 0);
for (int i = 1; i <= m; i++)
printf("%d\n", ans[i]);
return 0;
}
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
struct node {
pair<int, int> dat;
int lc, rc;
node()
{ lc = rc = 0; }
} hp[MAXN];
int merge(int a, int b)
{
if (a == 0 || b == 0) return a+b;
if (hp[a].dat > hp[b].dat) swap(a, b);
hp[a].lc = merge(hp[a].lc, b);
swap(hp[a].lc, hp[a].rc);
return a;
}
pair<int,int> pop(int &a)
{
pair<int, int> ans = hp[a].dat;
a = merge(hp[a].lc, hp[a].rc);
return ans;
}
int del[MAXN], fa[MAXN], tree[MAXN];
inline int findf(int nd)
{ return fa[nd]?fa[nd]=findf(fa[nd]):nd; }
int n, m, u;
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%d", &u);
hp[i].dat = make_pair(u, i);
tree[i] = i;
}
int opt, x, y;
for (int i = 1; i <= m; i++) {
scanf("%d", &opt);
if (opt == 1) {
scanf("%d%d", &x, &y);
if (del[x] || del[y] || findf(x) == findf(y)) continue;
x = findf(x), y = findf(y);
fa[x] = y, tree[y] = merge(tree[x], tree[y]);
} else {
scanf("%d", &x);
if (del[x]) puts("-1");
else {
x = findf(x);
pair<int, int> ans = pop(tree[x]);
del[ans.second] = 1;
printf("%d\n", ans.first);
}
}
}
return 0;
}
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 300005;
int chl[MAXN][2], fa[MAXN], dat[MAXN], sum[MAXN], rev[MAXN];
int stk[MAXN], top;
inline bool is_rt(int x)
{ return chl[fa[x]][0] != x && chl[fa[x]][1] != x; }
inline void pdw(int nd)
{
if (chl[nd][0]) rev[chl[nd][0]] ^= rev[nd];
if (chl[nd][1]) rev[chl[nd][1]] ^= rev[nd];
if (rev[nd]) swap(chl[nd][0], chl[nd][1]), rev[nd] = 0;
}
inline void update(int nd)
{ sum[nd] = dat[nd]^sum[chl[nd][0]]^sum[chl[nd][1]]; }
void zig(int nd)
{
int p = fa[nd], g = fa[p], tp = chl[p][0] != nd, tg = chl[g][0] != p;
int son = chl[nd][tp^1];
if (son) fa[son] = p;
if (!is_rt(p)) chl[g][tg] = nd;
fa[p] = nd, fa[nd] = g, chl[nd][tp^1] = p, chl[p][tp] = son;
update(p), update(nd);
}
void splay(int nd)
{
stk[top = 1] = nd;
for (int i = nd; !is_rt(i); i = fa[i]) stk[++top] = fa[i];
while (top) pdw(stk[top--]);
while (!is_rt(nd)) {
int p = fa[nd], g = fa[p], tp = chl[p][0] != nd, tg = chl[g][0] != p;
if (is_rt(p)) { zig(nd); break; }
else if (tp == tg) zig(p), zig(nd);
else zig(nd), zig(nd);
}
}
void access(int x)
{
for (int y = 0; x; x = fa[y = x])
splay(x), chl[x][1] = y, update(x);
}
void make_rt(int x)
{
access(x), splay(x), rev[x] ^= 1;
}
inline void link(int x, int y)
{ make_rt(x), fa[x] = y, access(x); }
inline void cut(int x, int y)
{
make_rt(x), access(y), splay(y);
if (chl[y][0] != x) return;
chl[y][0] = fa[x] = 0;
update(y);
}
int findf(int x)
{
access(x), splay(x);
while (chl[x][0]) x = chl[x][0];
return x;
}
int query(int x, int y)
{
make_rt(x), access(y), splay(y);
return sum[chl[y][0]]^dat[y];
}
void modify(int x, int y)
{
access(x), splay(x), dat[x] = y, update(x);
}
int n, m;
inline int read()
{
int a = 0, c;
do c = getchar(); while (!isdigit(c));
while (isdigit(c)) {
a = a*10+c-'0';
c = getchar();
}
return a;
}
int main()
{
n = read(), m = read();
for (int i = 1; i <= n; i++)
dat[i] = read();
int opt, x, y;
for (int i = 1; i <= m; i++) {
opt = read(), x = read(), y = read();
if (opt == 0) {
printf("%d\n", query(x, y));
} else if (opt == 1) {
int a = findf(x), b = findf(y);
if (a == b) continue;
link(x, y);
} else if (opt == 2) {
cut(x, y);
} else {
modify(x, y);
}
}
return 0;
}
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
struct node {
int to, next;
} edge[MAXN*2];
int head[MAXN], top = 0;
inline void push(int i, int j)
{ edge[++top] = (node) {j, head[i]}, head[i] = top; }
int dfn[MAXN], low[MAXN], dfn_top = 0;
int cur[MAXN];
int n, m;
void tarjan(int nd, int f)
{
// cerr << f << "-->" << nd << endl;
dfn[nd] = ++dfn_top, low[nd] = dfn[nd];
int cnt = 0;
for (int i = head[nd]; i; i = edge[i].next) {
int to = edge[i].to;
if (to == f) continue;
if (dfn[to]) low[nd] = min(low[nd], dfn[to]);
else {
cnt++, tarjan(to, nd), low[nd] = min(low[nd], low[to]);
if (f && low[to] >= dfn[nd]) cur[nd] = 1;
}
}
if (!f && cnt >= 2) cur[nd] = 1;
}
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i++) {
int u, v;
scanf("%d%d", &u, &v);
push(u, v), push(v, u);
}
for (int i = 1; i <= n; i++)
if (!dfn[i])
tarjan(i, 0);
int cnt = 0;
for (int i = 1; i <= n; i++)
if (cur[i])
cnt++;
printf("%d\n", cnt);
for (int i = 1; i <= n; i++)
if (cur[i])
printf("%d ", i);
puts("");
return 0;
}
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 20005;
int chl[MAXN][26], fail[MAXN], top = 0, root = 0;
int vis[MAXN];
struct node {
int to, next;
} edge[MAXN*2];
int head[MAXN], top_tp = 0;
inline void push(int i, int j)
{ edge[++top_tp] = (node) {j, head[i]}, head[i] = top_tp; }
int pos[MAXN];
inline void push(int &nd, const char *str, int id)
{
if (!nd) nd = ++top;
if (*str != '\0') push(chl[nd][*str-'a'], str+1, id);
else pos[id] = nd;
}
queue<int> que;
void build()
{
int nd = root; que.push(nd);
while (!que.empty()) {
int nd = que.front(); que.pop();
for (int i = 0; i < 26; i++) {
if (!chl[nd][i]) continue;
int p = fail[nd];
while (p && !chl[p][i]) p = fail[p];
if (!p) fail[chl[nd][i]] = root;
else fail[chl[nd][i]] = chl[p][i];
que.push(chl[nd][i]);
}
}
for (int i = 2; i <= top; i++) push(fail[i], i);
}
void match(char *str)
{
int nd = root;
for (char *p = str; *p != '\0'; ++p) {
while (nd && !chl[nd][*p-'a']) nd = fail[nd];
if (!nd) nd = root;
else { nd = chl[nd][*p-'a'], vis[nd]++; }
}
}
void display(int nd, int tab, char from)
{
if (!nd) return;
for (int i = 1; i <= tab; i++) putchar(' ');
printf("--%c--> %d, fail = %d, vis = %d\n", from, nd, fail[nd], vis[nd]);
for (int i = 0; i < 26; i++) {
if (chl[nd][i]) display(chl[nd][i], tab+2, i+'a');
}
}
void dfs1(int nd)
{
for (int i = head[nd]; i; i = edge[i].next) {
int to = edge[i].to;
dfs1(to), vis[nd] += vis[to];
}
}
char str[151][75];
int n;
char s[1000005];
int main()
{
while (scanf("%d", &n)) {
if (n == 0) break;
root = top = top_tp = 0;
memset(head, 0, sizeof head), memset(chl, 0, sizeof chl), memset(fail, 0, sizeof fail);
memset(vis, 0, sizeof vis);
for (int i = 1; i <= n; i++) scanf("%s", str[i]), push(root, str[i], i);
scanf("%s", s);
build();
match(s);
dfs1(root);
int max_val = 0;
for (int i = 1; i <= n; i++) {
max_val = max(max_val, vis[pos[i]]);
}
printf("%d\n", max_val);
for (int i = 1; i <= n; i++)
if (vis[pos[i]] == max_val)
puts(str[i]);
}
return 0;
}
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1005;
int n, m, e, u, v;
inline int read()
{
int a = 0, c;
do c = getchar(); while (!isdigit(c));
while (isdigit(c)) {
a = a*10+c-'0';
c = getchar();
}
return a;
}
struct node {
int to, next;
} edge[MAXN*MAXN];
int head[MAXN], top = 0;
inline void push(int i, int j)
{ edge[++top] = (node) {j, head[i]}, head[i] = top; }
int link[MAXN], vis[MAXN];
int s[MAXN];
bool arg(int nd)
{
for (int i = head[nd]; i; i = edge[i].next) {
int to = edge[i].to;
if (vis[to]) continue;
vis[to] = 1;
if (!link[to] || arg(link[to])) {
link[to] = nd;
s[nd] = 1;
return 1;
}
}
return 0;
}
void match()
{
int cnt = 0;
for (int i = 1; i <= n; i++) {
memset(vis, 0, sizeof vis);
if (!s[i] && arg(i)) cnt++;
}
printf("%d\n", cnt);
}
int main()
{
n = read(), m = read(), e = read();
for (int i = 1; i <= e; i++) {
u = read(), v = read();
if (u > n || v > m) continue;
push(u, v);
}
match();
return 0;
}
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 105;
double A[MAXN][MAXN];
int n;
void solve()
{
for (int i = 1; i <= n; i++) {
int pos = i;
while (pos <= n && A[pos][i] == 0) pos++;
if (pos > n) {
puts("No Solution");
return;
}
swap(A[pos], A[i]);
for (int j = 1; j <= n; j++) {
if (j == i) continue;
double tmp = -A[j][i]/A[i][i];
for (int k = 1; k <= n+1; k++)
A[j][k] += A[i][k]*tmp;
}
}
for (int i = 1; i <= n; i++)
printf("%.2f\n", A[i][n+1]/A[i][i]);
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n+1; j++)
scanf("%lf", &A[i][j]);
solve();
return 0;
}
和拉格朗日插值法类似,就是构造一个方程满足所有方程组。考虑。设为满足的数,,则可以构造:
#include <bits/stdc++.h>
using namespace std;
const int mod = 999911659;
const int a[] = {2, 3, 4679, 35617}, M = mod-1;
int power(int a, int b, int mod)
{
int ans = 1;
for (int i = 0; i <= 30; i++) {
if ((b>>i)&1) ans = (long long)ans*a%mod;
a = (long long)a*a%mod;
}
return ans;
}
inline int gcd(int a, int b)
{ return b==0?a:gcd(b, a%b); }
int ext_gcd(int a, int b, int &x, int &y)
{
if (b == 0) {
x = 1, y = 0;
return a;
}
int ans = ext_gcd(b, a%b, y, x);
y = y-a/b*x;
return ans;
}
int inv(int a, int m) // (a, b) = 1
{
int x, y;
ext_gcd(a, m, x, y);
return (x%m+m)%m;
}
int fac[4][40005], ifac[4][40005];
inline int choose(int n, int m, int mod_id)
{
if (n < m) return 0;
return (long long)fac[mod_id][n]*ifac[mod_id][m]%a[mod_id]*ifac[mod_id][n-m]%a[mod_id];
}
inline int lucas(int n, int m, int mod_id)
{
if (n < a[mod_id]) return choose(n, m, mod_id);
return (long long)lucas(n/a[mod_id], m/a[mod_id], mod_id)*choose(n%a[mod_id], m%a[mod_id], mod_id)%a[mod_id];
}
inline int choose_mod(int n, int m)
{
int ans[4], x = 0;
// cerr << n << " " << m << endl;
for (int i = 0; i < 4; i++) {
ans[i] = lucas(n, m, i);
// cerr << ans[i] << " ";
}
// cerr << endl;
for (int i = 0; i < 4; i++) x = (x+(long long)M/a[i]*inv(M/a[i]%a[i], a[i])%M*ans[i]%M)%M;
// cerr << x << endl;
return x;
}
int n, g;
int main()
{
scanf("%d%d", &n, &g);
if (g%mod == 0) {
puts("0");
return 0;
}
for (int i = 0; i < 4; i++) fac[i][0] = ifac[i][0] = 1;
for (int i = 0; i < 4; i++) {
for (int j = 1; j < a[i]; j++)
fac[i][j] = (long long)fac[i][j-1]*j%a[i];
for (int j = 1; j < a[i]; j++)
ifac[i][j] = (long long)ifac[i][j-1]*inv(j, a[i])%a[i];
}
// cerr << lucas(4, 1, 0) << endl;
int ans = 0;
for (int i = 1; i*i <= n; i++)
if (n%i == 0) {
ans = (ans+choose_mod(n, i))%M;
if (n/i > i) ans = (ans+choose_mod(n, n/i))%M;
}
printf("%d\n", power(g, ans, mod));
return 0;
}
次多项式满足,则满足:
2780: [Spoj]8093 Sevenk Love Oimaster
题意:给定若干个模式串,多组询问,问有多少个模式串包含作为其子串。
对模式串建立广义后缀自动机。对于每一个模式串,找到他所有前缀的状态并在其集合中加入。这样,对于一个询问,先找到他的位置,然后答案就是其子树中set并的大小。可以用平衡树/启发式合并,或者线段树合并来维护。
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
struct SAM {
int chl[MAXN][26], top, root, fa[MAXN], maxl[MAXN];
set<int> right_set[MAXN];
int pos[MAXN];
int dp[MAXN];
struct node {
int to, next;
} edge[MAXN];
int head[MAXN], top_tp;
inline void push_edge(int i, int j)
{ edge[++top_tp] = (node) {j, head[i]}, head[i] = top_tp; }
void clear()
{
memset(chl, 0, sizeof chl), top_tp = top = root = 1;
memset(fa, 0, sizeof fa), memset(maxl, 0, sizeof maxl);
}
SAM()
{ clear(); }
int push(int nd, int x)
{
int p = nd, np = ++top; maxl[np] = maxl[p]+1;
while (p && !chl[p][x]) chl[p][x] = np, p = fa[p];
if (!p) fa[np] = root;
else {
int q = chl[p][x];
if (maxl[q] == maxl[p]+1) fa[np] = q;
else {
int nq = ++top; maxl[nq] = maxl[p]+1, memcpy(chl[nq], chl[q], sizeof chl[q]);
fa[nq] = fa[q], fa[q] = fa[np] = nq;
while (p && chl[p][x] == q) chl[p][x] = nq, p = fa[p];
}
}
return np;
}
int get_pos(char *str)
{
int nd = root;
for (char *p = str; *p != '\0'; ++p) {
if (!chl[nd][*p-'a']) return -1;
nd = chl[nd][*p-'a'];
}
return nd;
}
int merge(int a, int b)
{
if (right_set[a].size() < right_set[b].size()) swap(a, b);
for (set<int>::iterator j = right_set[b].begin(); j != right_set[b].end(); ++j)
right_set[a].insert(*j);
return a;
}
void dfs(int nd)
{
for (int i = head[nd]; i; i = edge[i].next) {
int to = edge[i].to;
dfs(to);
}
for (int i = head[nd]; i; i = edge[i].next) {
int to = edge[i].to;
pos[nd] = merge(pos[nd], pos[to]);
}
dp[nd] = right_set[pos[nd]].size();
}
inline void get_ans()
{
for (int i = 1; i <= top; i++) {
pos[i] = i;
if (fa[i]) push_edge(fa[i], i);
}
dfs(root);
}
};
struct trie {
int chl[MAXN][26], fa[MAXN], stat[MAXN], top, root;
SAM sam;
int fin[MAXN], fin_top;
void clear()
{
sam.clear(), fin_top = top = root = 0;
memset(stat, 0, sizeof stat);
}
trie()
{ clear(); }
inline void push(int &nd, const char *str)
{
if (!nd) nd = ++top;
if (*str != '\0') push(chl[nd][*str-'a'], str+1), fa[chl[nd][*str-'a']] = nd;
else fin[++fin_top] = nd;
}
inline void push(const char *str)
{ push(root, str); }
queue<int> que;
void build_sam()
{
stat[root] = sam.root, que.push(root);
while (!que.empty()) {
int nd = que.front(); que.pop();
for (int i = 0; i < 26; i++) {
if (!chl[nd][i]) continue;
stat[chl[nd][i]] = sam.push(stat[nd], i);
que.push(chl[nd][i]);
}
}
}
void paint()
{
for (int i = 1; i <= fin_top; i++) {
for (register int j = fin[i]; j; j = fa[j])
sam.right_set[stat[j]].insert(i);
}
}
} T;
int n, q;
char s[400005];
int pos[60005];
int main()
{
scanf("%d%d", &n, &q);
for (int i = 1; i <= n; i++) {
scanf("%s", s);
T.push(s);
}
T.build_sam();
T.paint();
for (int i = 1; i <= q; i++) {
scanf("%s", s);
pos[i] = T.sam.get_pos(s);
}
T.sam.get_ans();
for (int i = 1; i <= q; i++) {
if (pos[i] == -1) puts("0");
else printf("%d\n", T.sam.dp[pos[i]]);
}
return 0;
}
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 8000005, N = 50005;
int chl[MAXN][2], fa[MAXN], top = 0;
int dat[MAXN];
int root[N];
int siz[MAXN];
void update(int nd)
{ siz[nd] = (chl[nd][0]!=0)*siz[chl[nd][0]]+(chl[nd][1]!=0)*siz[chl[nd][1]]+1; }
void zig(int nd, int id)
{
int p = fa[nd], g = fa[p], tp = chl[p][0] != nd, tg = chl[g][0] != p;
int son = chl[nd][tp^1];
if (son) fa[son] = p;
if (g) chl[g][tg] = nd;
else root[id] = nd;
fa[p] = nd, fa[nd] = g, chl[nd][tp^1] = p, chl[p][tp] = son;
update(p), update(nd);
}
void splay(int nd, int id, int tar = 0)
{
while (fa[nd] != tar) {
// cerr << nd << " " << fa[nd] << endl;
int p = fa[nd], g = fa[p], tp = chl[p][0] != nd, tg = chl[g][0] != p;
if (g == tar) { zig(nd, id); break; }
else if (tp == tg) zig(p, id), zig(nd, id);
else zig(nd, id), zig(nd, id);
}
}
int get_rank(int nd, int id)
{
splay(nd, id);
return chl[nd][0]+1;
}
int number_ls(int k, int id)
{
int ans = 0, nd = root[id];
while (nd) {
if (dat[nd] < k) ans += siz[chl[nd][0]]+1, nd = chl[nd][1];
else nd = chl[nd][0];
}
return ans;
}
int number_le(int k, int id)
{
int ans = 0, nd = root[id];
while (nd) {
if (dat[nd] <= k) ans += siz[chl[nd][0]]+1, nd = chl[nd][1];
else nd = chl[nd][0];
}
return ans;
}
int find_kth(int k, int id)
{
int nd = root[id];
while (1) {
if (siz[chl[nd][0]]+1 == k) break;
else if (siz[chl[nd][0]]+1 > k) nd = chl[nd][0];
else k -= siz[chl[nd][0]]+1, nd = chl[nd][1];
}
splay(nd, id);
return nd;
}
int pre_ele(int dt, int id)
{
int ls = number_ls(dt, id);
if (ls == 0) return 0;
return find_kth(ls, id);
}
int nxt_ele(int dt, int id)
{
int gt = number_le(dt, id)+1;
if (gt > siz[root[id]]) return 0;
return find_kth(gt, id);
}
int push(int &nd, int dt, int f = 0)
{
if (nd == 0) {
nd = ++top, dat[nd] = dt, update(nd);
fa[nd] = f;
return top;
}
siz[nd]++;
if (dt <= dat[nd]) return push(chl[nd][0], dt, nd);
else return push(chl[nd][1], dt, nd);
}
int pop_ele(int dt, int id)
{
// printf("pop %d ---> %d\n", dt, id);
int num = number_ls(dt, id)+1;
// cerr << id << "j" << num << endl;
int pre = find_kth(num-1, id), nxt = find_kth(num+1, id);
// cerr << pre << " " << nxt << endl;
// cerr << dat[nxt] << " " << dat[pre] << endl;
splay(pre, id), splay(nxt, id, pre);
chl[nxt][0] = 0, update(nxt), update(pre);
// puts("---");
}
void push_ele(int dt, int id)
{
// printf("push %d --> %d\n", dt, id);
int nd = push(root[id], dt);
splay(nd, id);
}
void display(int nd, int tab)
{
if (!nd) return;
for (int i = 1; i <= tab; i++) putchar(' ');
printf("siz = %d, dat = %d\n", siz[nd], dat[nd]);
display(chl[nd][0], tab+2), display(chl[nd][1], tab+2);
}
int c[N], a[N], n, m;
inline int lowbit(int i)
{ return i&(-i); }
void del(int nd, int dt)
{
for (; nd <= n; nd += lowbit(nd))
pop_ele(dt, nd);
}
void add(int nd, int dt)
{
for (; nd <= n; nd += lowbit(nd))
push_ele(dt, nd);
}
void modify(int nd, int dt)
{
del(nd, a[nd]), add(nd, dt), a[nd] = dt;
}
int number_prefix_ls(int pos, int dt)
{
int ans = 0;
for (; pos; pos -= lowbit(pos))
ans += number_ls(dt, pos)-1;
return ans;
}
int number_seg_ls(int L, int R, int dt)
{ return number_prefix_ls(R, dt)-number_prefix_ls(L-1, dt); }
int number_prefix_le(int pos, int dt)
{
int ans = 0;
for (; pos; pos -= lowbit(pos))
ans += number_le(dt, pos)-1;
return ans;
}
int number_seg_le(int L, int R, int dt)
{ return number_prefix_le(R, dt)-number_prefix_le(L-1, dt); }
int find_seg_kth(int Lpos, int Rpos, int dt)
{
int L = 0, R = 1e8, Mid;
while (L <= R) {
Mid = (L+R)>>1;
if (number_seg_le(Lpos, Rpos, Mid) >= dt) R = Mid-1;
else L = Mid+1;
}
return R+1;
}
int find_seg_pre(int Lpos, int Rpos, int dt)
{
int num = number_seg_ls(Lpos, Rpos, dt);
if (num == 0) return INT_MIN+1;
return find_seg_kth(Lpos, Rpos, num);
}
int find_seg_nxt(int Lpos, int Rpos, int dt)
{
int num = number_seg_le(Lpos, Rpos, dt)+1;
if (num > Rpos-Lpos+1) return INT_MAX;
return find_seg_kth(Lpos, Rpos, num);
}
inline int read()
{
int a = 0;
scanf("%d", &a);
return a;
}
int main()
{
// freopen("psh.in", "r", stdin);
// freopen("psh.out", "w", stdout);
n = read(), m = read();
for (int i = 1; i <= n; i++) a[i] = read();
for (int i = 1; i <= n; i++)
push_ele(INT_MIN+1, i), push_ele(INT_MAX, i);
for (int i = 1; i <= n; i++)
add(i, a[i]);
int cnt = 0;
for (int i = 1; i <= m; i++) {
int opt, l, r, k;
opt = read();
cnt++;
if (opt == 1) {
l = read(), r = read(), k = read();
printf("%d\n", number_seg_ls(l, r, k)+1);
} else if (opt == 2) {
l = read(), r = read(), k = read();
printf("%d\n", find_seg_kth(l, r, k));
} else if (opt == 3) {
l = read(), r = read();
modify(l, r);
cnt--;
} else if (opt == 4) {
l = read(), r = read(), k = read();
printf("%d\n", find_seg_pre(l, r, k));
} else {
l = read(), r = read(), k = read();
printf("%d\n", find_seg_nxt(l, r, k));
}
}
return 0;
}
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 50005;
struct node {
int to, next;
} edge[MAXN];
int head[MAXN], top = 0;
inline void push(int i, int j)
{ edge[++top] = (node) {j, head[i]}, head[i] = top; }
int dfn[MAXN], dfn_top = 0, low[MAXN], vis[MAXN], stk[MAXN], stk_top = 0;
int g[MAXN], gtop = 0, gsiz[MAXN];
int d[MAXN];
int n, m;
void tarjan(int nd)
{
stk[++top] = nd, vis[nd] = 1, dfn[nd] = low[nd] = ++dfn_top;
for (int i = head[nd]; i; i = edge[i].next) {
int to = edge[i].to;
if (!dfn[to]) tarjan(to), low[nd] = min(low[nd], low[to]);
else if (vis[to]) low[nd] = min(low[nd], dfn[to]);
}
if (dfn[nd] == low[nd]) {
gtop++;
int now;
do {
now = stk[top--];
vis[now] = 0; // !!!
g[now] = gtop, gsiz[gtop]++;
} while (now != nd);
}
}
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i++) {
int u, v;
scanf("%d%d", &u, &v);
push(u, v);
}
for (int i = 1; i <= n; i++)
if (!dfn[i])
tarjan(i);
for (int i = 1; i <= n; i++) {
for (int j = head[i]; j; j = edge[j].next) {
int to = edge[j].to;
d[g[i]] += (g[to] != g[i]);
}
}
int pos = 0, cnt = 0;
for (int i = 1; i <= gtop; i++)
if (d[i] == 0) {
pos = i, cnt++;
}
if (cnt != 1) puts("0");
else printf("%d\n", gsiz[pos]);
return 0;
}
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1000005;
char S[MAXN], T[MAXN];
int nxt[MAXN];
int main()
{
scanf("%s", S+1), scanf("%s", T+1);
nxt[1] = 0;
int pL = strlen(T+1), sL = strlen(S+1), cnt = 0;
int p = 0;
for (int i = 2; i <= pL; i++) {
while (p && T[p+1] != T[i]) p = nxt[p];
if (T[p+1] == T[i]) p++;
nxt[i] = p;
}
p = 0;
for (int i = 1; i <= sL; i++) {
while (p && T[p+1] != S[i]) p = nxt[p];
if (T[p+1] == S[i]) p++;
if (p == pL) {
cnt++;
p = nxt[p];
}
}
printf("%d\n", cnt);
return 0;
}
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1000005;
struct SA {
struct node {
int k[2], id;
node(){}
node(int x, int y) {k[0] = x, k[1] = y; }
} RE[MAXN], RT[MAXN];
int a[MAXN], sum[MAXN], SA[MAXN], rank[MAXN], n;
void radix_sort()
{
for (int y = 1; y >= 0; y--) {
memset(sum, 0, sizeof sum);
for (int i = 1; i <= n; i++) RT[i] = RE[i];
for (int i = 1; i <= n; i++) sum[RT[i].k[y]]++;
for (int i = 1; i < MAXN; i++) sum[i] += sum[i-1];
for (int i = n; i >= 1; i--) RE[sum[RT[i].k[y]]--] = RT[i];
}
for (int i = 1; i <= n; i++) {
rank[RE[i].id] = rank[RE[i-1].id];
if (RE[i].k[0] != RE[i-1].k[0] || RE[i].k[1] != RE[i-1].k[1])
rank[RE[i].id]++;
}
}
void build_SA()
{
for (int i = 1; i <= n; i++) RE[i] = node(a[i], 0), RE[i].id = i;
radix_sort();
for (int k = 1; k < n; k <<= 1) {
for (int j = 1; j <= n; j++) RE[j] = node(rank[j], j+k<=n?rank[j+k]:0), RE[j].id = j;
radix_sort();
}
for (int i = 1; i <= n; i++)
SA[rank[i]] = i;
}
} sa;
char str[MAXN];
int main()
{
scanf("%s", str+1);
sa.n = strlen(str+1);
for (int i = 1; i <= sa.n; i++) sa.a[i] = str[i];
sa.build_SA();
for (int i = 1; i <= sa.n; i++)
printf("%d ", sa.SA[i]);
puts("");
return 0;
}
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
int have0 = 0;
struct linear_base {
long long a[70];
int top;
linear_base()
{ top = 0; }
void push(long long x)
{
for (int i = 1; i <= top; i++)
if ((x^a[i]) < x)
x ^= a[i];
if (!x) { have0 = 1; return; }
a[++top] = x;
int i = top;
for (; i > 1 && a[i] > a[i-1]; i--)
swap(a[i], a[i-1]);
for (i--; i >= 1; i--)
if ((x^a[i]) < a[i])
a[i] ^= x;
}
} lb;
int main()
{
int n, m;
long long x;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%lld", &x), lb.push(x);
// for (int i = 1; i <= lb.top; i++) cerr << lb.a[i] << " ";
// cerr << endl;
}
// puts("hahahahaha");
// cerr << lb.top << endl;
scanf("%d", &m);
for (int i = 1; i <= m; i++) {
scanf("%lld", &x);
x -= have0;
if (x > (1ll<<lb.top)) puts("-1");
else {
// cerr << "--" << x << " " << lb.top << endl;
// cerr << lb.a[9] << endl;
long long ans = 0;
for (int j = 0; j <= 60; j++)
if (x&(1ll<<j)) {
ans ^= lb.a[lb.top-j];
// cerr << lb.top-j << endl;
}
printf("%lld\n", ans);
}
}
return 0;
}
行列建点,增广路对应方案。
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 205;
int n, m, k;
int l[MAXN], c[MAXN];
struct node {
int to, next, flow, cost, neg;
} edge[MAXN*MAXN*10];
int head[MAXN], top = 0;
inline void push(int i, int j, int f, int c)
{
++top, edge[top] = (node) {j, head[i], f, c, top+1}, head[i] = top;
++top, edge[top] = (node) {i, head[j], 0, -c, top-1}, head[j] = top;
}
const int SS = MAXN-1, ST = MAXN-2, S = MAXN-3, T = MAXN-4;
int cnt = 0;
inline void push(int i, int j, int lb)
{
push(SS, j, lb, 0), push(i, ST, lb, 0);
cnt += lb;
}
int dis[MAXN], vis[MAXN];
deque<int> que;
bool spfa()
{
memset(dis, 127/3, sizeof dis);
memset(vis, 0, sizeof vis);
vis[SS] = 1, dis[SS] = 0, que.push_back(SS);
while (!que.empty()) {
int nd = que.front(); que.pop_front(), vis[nd] = 0;
for (int i = head[nd]; i; i = edge[i].next) {
int to = edge[i].to, f = edge[i].flow, c = edge[i].cost;
if (!f || dis[to] <= dis[nd]+c) continue;
dis[to] = dis[nd]+c;
if (!vis[to]) {
vis[to] = 1;
if (que.empty() || dis[to] > dis[que.front()]) que.push_back(to);
else que.push_front(to);
}
}
}
return dis[ST] <= 23333333;
}
int dfs(int nd, int flow)
{
if (nd == ST || !flow) return flow;
vis[nd] = 1;
int ans = 0, t;
for (int i = head[nd]; i; i = edge[i].next) {
int to = edge[i].to, f = edge[i].flow, c = edge[i].cost;
if (vis[to] || dis[to] != dis[nd]+c || !f) continue;
t = dfs(to, min(flow, f));
ans += t, flow -= t, edge[i].flow -= t, edge[edge[i].neg].flow += t;
if (!flow) break;
}
return ans;
}
void mcf(int &c, int &f)
{
c = f = 0;
int t;
while (spfa()) {
do {
memset(vis, 0, sizeof vis);
t = dfs(SS, INT_MAX);
f += t, c += t*dis[ST];
} while (t);
}
}
bool g[101][101];
int main()
{
scanf("%d%d%d", &n, &m, &k);
for (int i = 1; i <= n; i++) scanf("%d", &l[i]);
for (int i = 1; i <= m; i++) scanf("%d", &c[i]);
for (int i = 1; i <= k; i++) {
int u, v;
scanf("%d%d", &u, &v);
g[u][v] = true;
}
for (int i = 1; i <= n; i++) push(S, i, l[i]);
for (int j = 1; j <= m; j++) push(n+j, T, c[j]);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
if (!g[i][j])
push(i, n+j, 1, 1);
push(T, S, INT_MAX, 0);
int c, f;
mcf(c, f);
if (f != cnt) puts("JIONG!");
else printf("%d\n", c);
return 0;
}
TODO LIST: