模板整理
作者在多次程序爆炸后,痛定思痛,决定将各种算法和数据结构写法整理汇集成文。
数据结构
线段树
struct nd { int sum, tag, ln, rn, tn; nd() { sum = ln = rn = tn = 0, tag = -1; } };
struct node { int l, r; nd x; };
struct seg_tree {
node tr[_ << 2];
node C(node l, node r) { node t;
t.x.sum = l.x.sum + r.x.sum, t.l = l.l, t.r = r.r;
t.x.ln = (l.x.sum == l.r - l.l + 1) ? l.x.sum + r.x.ln : l.x.ln,
t.x.rn = (r.x.sum == r.r - r.l + 1) ? r.x.sum + l.x.rn : r.x.rn,
t.x.tn = std::max(std::max(l.x.tn, r.x.tn), l.x.rn + r.x.ln); return t;
}
void U(int p) { tr[p] = C(tr[ls], tr[rs]); }
void P(int p, int k) { tr[p].x.sum = tr[p].x.ln = tr[p].x.rn = tr[p].x.tn = (tr[p].r - tr[p].l + 1) * k, tr[p].x.tag = k; }
void D(int p) { if (~tr[p].x.tag) P(ls, tr[p].x.tag), P(rs, tr[p].x.tag), tr[p].x.tag = -1; }
void B(int l, int r, int p) {
if (l == r) { tr[p].l = tr[p].r = l; return; } int mid = (l + r) >> 1;
B(l, mid, ls), B(mid + 1, r, rs), U(p);
}
void M(int l, int r, int p) {
if (r < tr[p].l or tr[p].r < l) return;
if (l <= tr[p].l and tr[p].r <= r) { P(p, 1); return; } D(p);
M(l, r, ls), M(l, r, rs), U(p);
}
int E(int l, int r, int p) {
if (r < tr[p].l or tr[p].r < l) return 0;
if (l <= tr[p].l and tr[p].r <= r) { int res = tr[p].r - tr[p].l + 1 - tr[p].x.sum; P(p, 1); return res; } D(p);
int res = E(l, r, ls) + E(l, r, rs); U(p); return res;
}
void F(int l, int r, int &k, int p) {
if (r < tr[p].l or tr[p].r < l or !k) return;
if (l <= tr[p].l and tr[p].r <= r and tr[p].x.sum <= k) { k -= tr[p].x.sum, P(p, 0); return; } D(p);
if (tr[ls].x.sum) F(l, r, k, ls); if (tr[rs].x.sum) F(l, r, k, rs); U(p);
}
node Q(int l, int r, int p) {
if (r < tr[p].l or tr[p].r < l) return node();
if (l <= tr[p].l and tr[p].r <= r) return tr[p]; D(p);
return C(Q(l, r, ls), Q(l, r, rs));
}
}T;
//Luogu P4513
李超树
void Upd(int s, int t, int v, int p) {
int mid = (s + t) >> 1;
int c = Cmp(Calc(u, mid), Calc(v, mid));
if (c == -1 or (!c and u > v)) std::swap(u, v);
if (s == t) return;
int cl = Cmp(Calc(u, s), Calc(v, s)),
cr = Cmp(Calc(u, t), Calc(v, t));
if (cl == -1 or (!cl and u > v)) Upd(s, mid, v, ls);
if (cr == -1 or (!cr and u > v)) Upd(mid + 1, t, v, rs);
}
void Modify(int l, int r, int s, int t, int v, int p) {
if (r < s or t < l) return;
if (l <= s and t <= r) { Upd(s, t, v, p); return; } int mid = (s + t) >> 1;
Modify(l, r, s, mid, v, ls), Modify(l, r, mid + 1, t, v, rs);
}
void Solve(int id, int x) {
if (!Ans) { Ans = id; return; }
int c = Cmp(Calc(id, x), Calc(Ans, x));
if (c == 1 or (!c and id < Ans)) Ans = id;
}
void Query(int s, int t, int d, int p) {
if (d < s or t < d) return;
Solve(u, d); if (s == t) return;
int mid = (s + t) >> 1;
Query(s, mid, d, ls), Query(mid + 1, t, d, rs);
}
平衡树
void U(int p) {
sum[p] = sum[ls[p]] + sum[rs[p]] + val[p], siz[p] = siz[ls[p]] + siz[rs[p]] + 1,
mx[p] = std::max(std::max(mx[ls[p]], mx[rs[p]]), val[p]);
ln[p] = std::max(ln[ls[p]], sum[ls[p]] + val[p] + ln[rs[p]]),
rn[p] = std::max(rn[rs[p]], sum[rs[p]] + val[p] + rn[ls[p]]),
tn[p] = std::max(std::max(tn[ls[p]], tn[rs[p]]), val[p] + rn[ls[p]] + ln[rs[p]]);
}
void N(int p) { std::swap(ln[p], rn[p]), neg[p] ^= 1, std::swap(ls[p], rs[p]); }
void C(int p, int k) { ln[p] = rn[p] = tn[p] = std::max(0, sum[p] = siz[p] * k), mx[p] = tag[p] = val[p] = k; }
void D(int p) {
if (neg[p]) N(ls[p]), N(rs[p]), neg[p] = 0;
if (tag[p] != inf) C(ls[p], tag[p]), C(rs[p], tag[p]), tag[p] = inf;
}
void S(int p, int k, int &x, int &y) {
if (!p) { x = y = 0; return; } D(p);
if (k < siz[ls[p]] + 1) y = p, S(ls[p], k, x, ls[y]);
else x = p, S(rs[p], k - siz[ls[p]] - 1, rs[x], y); U(p);
}
int M(int x, int y) {
if (!x or !y) return x | y;
if (rnd[x] > rnd[y]) { D(x), rs[x] = M(rs[x], y), U(x); return x; }
else { D(y), ls[y] = M(x, ls[y]), U(y); return y; }
}
int A(int k) { int p = *del ? del[(*del)--] : ++idx; ln[p] = rn[p] = tn[p] = std::max(0, mx[p] = sum[p] = val[p] = k), rnd[p] = rand(), siz[p] = 1, tag[p] = inf, neg[p] = 0; return p; }
void Er(int p) { if (!p) return; del[++*del] = p, Er(ls[p]), Er(rs[p]); }
int B(int l, int r) {
if (l > r) return 0; int mid = (l + r) >> 1, p = A(c[mid]);
ls[p] = B(l, mid - 1), rs[p] = B(mid + 1, r); U(p); return p;
}
void I() { int pos, tot;
std::cin >> pos >> tot;
lep(i, 1, tot) std::cin >> c[i];
int p = B(1, tot);
S(rt, pos, x, y), rt = M(M(x, p), y);
}
void E() { int pos, tot; std::cin >> pos >> tot; T(pos, pos + tot - 1); Er(y), rt = M(x, z); }
void K() { int pos, tot, c; std::cin >> pos >> tot >> c; T(pos, pos + tot - 1); C(y, c), rt = M(M(x, y), z); }
void R() { int pos, tot; std::cin >> pos >> tot; T(pos, pos + tot - 1); N(y), rt = M(M(x, y), z); }
void G() { int pos, tot; std::cin >> pos >> tot; T(pos, pos + tot - 1); std::cout << sum[y] << '\n', rt = M(M(x, y), z); }
void X() { if (mx[rt] < 0) std::cout << mx[rt] << '\n'; else std::cout << tn[rt] << '\n'; }
//Luogu P2042
左偏树
int Find(int x) { return fa[x] == x ? x : fa[x] = Find(fa[x]); }
int Merge(int x, int y) {
if (!x or !y) return x | y;
if (val[x] > val[y]) std::swap(x, y);
rs[x] = Merge(rs[x], y);
dist[x] = dist[rs[x]] + 1;
if (dist[ls[x]] < dist[rs[x]]) std::swap(ls[x], rs[x]);
fa[ls[x]] = fa[rs[x]] = fa[x] = x;
return x;
}
int Pop(int x) {
if (val[x] == -1) return -1;
int f = Find(x), res = val[f]; val[f] = -1;
fa[ls[f]] = ls[f], fa[rs[f]] = rs[f];
fa[f] = Merge(ls[f], rs[f]);
return res;
}
AC自动机
void B() {
std::queue <int> d;
lep(k, 0, 25) if (ch[0][k]) d.push(ch[0][k]);
while (!d.empty()) { int u = d.front(); d.pop();
lep(k, 0, 25) {
if (ch[u][k]) fail[ch[u][k]] = ch[fail[u]][k], d.push(ch[u][k]);
else ch[u][k] = ch[fail[u]][k];
}
}
}
void D(int u) { for (int v : e[u]) D(v), sum[u] += sum[v]; }
void G(char s[]) {
int len = std::strlen(s + 1), nw = 0;
lep(i, 1, len) nw = ch[nw][s[i] - 'a'], ++sum[nw];
lep(i, 1, idx) e[fail[i]].push_back(i);
D(0);
lep(i, 1, n) printf("%d\n", sum[ps[i]]);
}
//Luogu P5357
SAM
void Extend(int c) {
int p = Last, np = ++idx; Last = np;
len[np] = len[p] + 1;
while (p and !ch[p].count(c)) ch[p][c] = np, p = Link[p];
if (!p) Link[np] = 1;
else if (len[p] + 1 == len[ch[p][c]]) Link[np] = ch[p][c];
else {
int q = ch[p][c], nq = ++idx;
ch[nq] = ch[q], len[nq] = len[p] + 1,
Link[nq] = Link[q], Link[q] = Link[np] = nq;
while (p and ch[p][c] == q) ch[p][c] = nq, p = Link[p];
}
++num[np];
}
void Gets() {
lep(i, 1, idx) tot[len[i]]++;
lep(i, 1, n) tot[i] += tot[i - 1];
lep(i, 1, idx) sa[tot[len[i]]--] = i;
rep(i, idx, 1) num[Link[sa[i]]] += num[sa[i]];
lep(i, 1, idx) if (num[i] > 1) ans = std::max(ans, num[i] * len[i]);
}
算法
SA
int main() {
scanf("%s", s + 1); n = std::strlen(s + 1);
m = 200;
lep(i, 1, n) ++cnt[rk[i] = s[i]];
lep(i, 1, m) cnt[i] += cnt[i - 1];
rep(i, n, 1) sa[cnt[rk[i]]--] = i;
for (int w = 1; w <= n; w <<= 1, m = p) {
int cur = 0;
lep(i, n - w + 1, n) nsa[++cur] = i;
lep(i, 1, n) if (sa[i] > w) nsa[++cur] = sa[i] - w;
lep(i, 1, n) sa[i] = nsa[i];
lep(i, 0, m) cnt[i] = 0;
lep(i, 1, n) ++cnt[rk[i]];
lep(i, 1, m) cnt[i] += cnt[i - 1];
rep(i, n, 1) nsa[cnt[rk[sa[i]]]--] = sa[i]; p = 0;
lep(i, 1, n) {
if (rk[nsa[i]] == rk[nsa[i - 1]] and rk[nsa[i] + w] == rk[nsa[i - 1] + w]) nrk[nsa[i]] = p;
else nrk[nsa[i]] = ++p;
}
lep(i, 1, n) sa[i] = nsa[i], rk[i] = nrk[i];
if (p == n) break;
}
lep(i, 1, n) printf("%d ", sa[i]);
return 0;
}
Lython 分解
int n, ans, i = 1; char s[_];
int main() {
scanf("%s", s + 1), n = std::strlen(s + 1);
while (i <= n) {
int j = i, k = i + 1;
while (k <= n and s[j] <= s[k]) j = (s[j] == s[k++]) ? j + 1 : i;
while (i <= j) i += k - j, ans ^= i - 1;
}
printf("%d\n", ans);
return 0;
}
//Luogu P6114
最小表示法
int main() {
scanf("%d", & n);
lep(i, 1, n) scanf("%d", A + i), A[i + n] = A[i];
int i = 1;
while (i <= n * 2) {
int j = i, k = i + 1;
while (k <= n * 2 and A[j] <= A[k]) j = (A[j] == A[k++]) ? j + 1 : i;
while (i <= j) ans = (i <= n) ? i : ans, i += k - j;
}
lep(i, ans, n) printf("%d ", A[i]);
lep(i, 1, ans - 1) printf("%d ", A[i]);
return 0;
}
//Luogu P1368
CDQ 分治
void A(int x, int k) { while (x < lim) bt[x] = std::max(bt[x], k), bs[x] |= 1, x += x & -x; }
void E(int x) { while (x < lim) bt[x] = bs[x] = 0, x += x & -x; }
int Q(int x) { int res = 0; bool f = 0; while (x) f |= bs[x], res = std::max(res, bt[x]), x -= x & -x; return f ? res : -1; }
void S(int l, int r) {
if (l >= r) return;
int mid = (l + r) >> 1;
S(l, mid), S(mid + 1, r);
int len = l - 1, p = l - 1;
lep(i, mid + 1, r) {
while (p < mid and c[p + 1].x <= c[i].x) { ++p; if (c[p].op == 0) A(c[p].y, c[p].x + c[p].y); t[++len] = c[p]; }
if (c[i].op == 1) { int tmp = Q(c[i].y); if (~tmp) ans[c[i].t] = std::min(ans[c[i].t], c[i].x + c[i].y - tmp); }
t[++len] = c[i];
}
while (p < mid) t[++len] = c[++p];
lep(i, l, mid) if (c[i].op == 0) E(c[i].y);
lep(i, l, r) c[i] = t[i];
}
int main() {
scanf("%d%d", & n, & m);
lep(i, 1, n) scanf("%d%d", & x, & y), q[++tot] = { 0, 0, x + 1, y + 1 };
lep(i, 1, m) ans[i] = inf, scanf("%d%d%d", & op, & x, & y), q[++tot] = { op - 1, i, x + 1, y + 1 };
lep(i, 1, tot) c[i] = q[i];
S(1, tot);
lep(i, 1, tot) c[i] = q[i], c[i].x = lim - c[i].x;
S(1, tot);
lep(i, 1, tot) c[i] = q[i], c[i].y = lim - c[i].y;
S(1, tot);
lep(i, 1, tot) c[i] = q[i], c[i].x = lim - c[i].x, c[i].y = lim - c[i].y;
S(1, tot);
lep(i, 1, tot) if (q[i].op == 1) printf("%d\n", ans[q[i].t]);
return 0;
}
//Luogu P4169
LCA
void dfs1(int u,int f) {
siz[u] = 1, dep[u] = dep[fa[u] = f] + 1;
for(int i = head[u]; i ;i = nxt[i]) {
int v = to[i];
if(v == f) continue;
dfs1(v, u);
siz[u] += siz[v];
if(siz[v] > siz[Hson[u]]) Hson[u] = v;
}
}
void dfs2(int u,int tp) {
top[u] = tp;
if(!Hson[u]) return;
dfs2(Hson[u], tp);
for(int i = head[u]; i ;i = nxt[i]) {
int v = to[i];
if(v == fa[u] or v == Hson[u]) continue;
dfs2(v, v);
}
}
int LCA(int u,int v) {
while(top[u] != top[v]) {
if(dep[top[u]] < dep[top[v]]) swap(u, v);
u = fa[top[u]];
}
return dep[u] < dep[v] ? u : v;
}
点分治
void Getrt(int u, int f, int total) {
tmp[u] = 0; siz[u] = 1;
for (int i = head[u]; i ; i = e[i].nxt) {
int v = e[i].to;
if (v == f or vis[v]) continue;
Getrt(v, u, total); siz[u] += siz[v]; tmp[u] = max(tmp[u], siz[v]);
}
tmp[u] = max(tmp[u], total - siz[u]);
if (!root or tmp[u] < tmp[root]) root = u;
}
void solve(int u) {
vis[u] = true; calc(u);
for (int i = head[u]; i ; i = e[i].nxt) { int v = e[i].to;
if (vis[v]) continue;
root = 0; Getrt(v, 0, siz[v]);
solve(root);
}
}
DLX
void Init() {
lep(i, 0, m) {
A[i].l = i - 1, A[i].r = i + 1;
A[i].u = A[i].d = i;
}
A[0].r = 1, A[0].l = m, A[m].r = 0;
idx = m;
}
void Add(int x, int y) {
A[++idx] = { 0, 0, A[y].u, y, x, y };
A[A[y].u].d = idx, A[y].u = idx;
if (!row[x]) {
row[x] = idx;
A[idx].l = A[idx].r = idx;
}
else {
A[idx].l = A[row[x]].l, A[idx].r = row[x];
A[A[idx].l].r = A[row[x]].l = idx;
}
++lcnt[y];
}
void Remove(int y) {
for (int i = A[y].d; i != y; i = A[i].d)
for (int j = A[i].r; j != i; j = A[j].r)
A[A[j].u].d = A[j].d, A[A[j].d].u = A[j].u, --lcnt[A[j].y];
A[A[y].r].l = A[y].l, A[A[y].l].r = A[y].r;
}
void Resume(int y) {
A[A[y].r].l = y, A[A[y].l].r = y;
for (int i = A[y].d; i != y; i = A[i].d)
for (int j = A[i].l; j != i; j = A[j].l)
A[A[j].u].d = j, A[A[j].d].u = j, ++lcnt[A[j].y];
}
void Dance(int len) {
if (A[0].r == 0) {
lep(i, 1, len - 1) printf("%d ", ans[i]);
exit(0);
}
int id = 0;
for (int i = A[0].r; i; i = A[i].r)
if (!id or lcnt[i] < lcnt[id]) id = i;
Remove(id);
for (int i = A[id].d; i != id; i = A[i].d) {
ans[len] = A[i].x;
for (int j = A[i].r; j != i; j = A[j].r) Remove(A[j].y);
Dance(len + 1);
for (int j = A[i].l; j != i; j = A[j].l) Resume(A[j].y);
}
Resume(id);
}
tarjan
void tarjan(int u) {
S.push(u); in[u] = true;
low[u] = dfn[u] = ++cnt;
for (int i = head[u]; i ; i = nxt[i]) {
int v = to[i];
if (!dfn[v]) {
tarjan(v);
low[u] = min(low[u], low[v]);
}
else if (in[v])
low[u] = min(low[u], dfn[v]);
}
if (dfn[u] == low[u]) {
while (S.top() != u) {
val[u] += val[S.top()];
in[S.top()] = false, mtc[S.top()] = u, S.pop();
}
in[u] = false, mtc[u] = u, S.pop();
}
}
Johnson
void Solve() {
lep(i, 1, n) Add(0, i, 0);
Bellman_Ford(0);
lep(i, 1, m) e[i].w += dis[0][e[i].u] - dis[0][e[i].v];
lep(i, 1, n) {
Dijkstra(i); ans = 0;
lep(j, 1, n) {
if (dis[i][j] == inf) ans += 1ll * j * dis[i][j];
else ans += 1ll * j * (dis[i][j] - dis[0][i] + dis[0][j]);
}
printf("%lld\n", ans);
}
}
Dinic
bool bfs() {
while (!q.empty()) q.pop();
for (int i = 1; i <= N; ++i) dep[i] = 0;
dep[S] = 1, q.push(S);
while (!q.empty()) {
int u = q.front(); q.pop();
if (u == T) return true;
for (int i = head[u]; i ; i = e[i].nxt) { int v = e[i].to;
if (!dep[v] and e[i].cap)
dep[v] = dep[u] + 1, q.push(v);
}
}
return false;
}
LL dfs(int u, LL exp) {
if (u == T or !exp) return exp;
LL tot = 0;
for (int i = cur[u]; exp and i; i = e[i].nxt) { int v = e[i].to; cur[u] = i;
if (dep[v] != dep[u] + 1 or !e[i].cap) continue;
LL f = dfs(v, std::min(exp, e[i].cap));
if (f == 0) { dep[v] = 0; continue; }
e[i].cap -= f, e[i ^ 1].cap += f,
tot += f, exp -= f;
}
return tot;
}
int main() {
while (bfs()) {
for (int i = 1; i <= N; ++i) cur[i] = head[i];
ans += dfs(S, inf);
}
}
EK
bool bfs() {
while (!q.empty()) q.pop();
for (int i = 1; i <= N; ++i) pre[i] = 0, low[i] = 0;
pre[S] = -1, low[S] = inf, q.push(S);
while (!q.empty()) {
int u = q.front(); q.pop();
if (u == T) return true;
for (int i = head[u]; i ; i = e[i].nxt) {
int v = e[i].to;
if (!pre[v] and e[i].cap > 0)
pre[v] = i, low[v] = std::min(low[u], e[i].cap), q.push(v);
}
}
return false;
}
int main() {
while (bfs()) {
for (int j = T; j != S; j = e[pre[j]].fro)
e[pre[j]].cap -= low[T],
e[pre[j] ^ 1].cap += low[T];
ans += low[T];
}
}
有源汇上下界最大流
int main() {
s = 0, t = n + m + 1;
lep(i, 1, m) scanf("%d", & G),
Mod(n + i, t, G), Add(n + i, t, inf - G), Add(t, n + i, 0);
lep(i, 1, n) {
scanf("%d%d", & C, & D);
Add(s, i, D), Add(i, s, 0);
while (C--) {
scanf("%d%d%d", & x, & l, & r); ++x;
Mod(i, n + x, l),
Add(i, n + x, r - l), Add(n + x, i, 0);
}
}
S = t + 1, T = S + 1;
lep(i, s, t) if (val[i] > 0) Add(S, i, val[i]), Add(i, S, 0), sum += val[i];
else if (val[i] < 0) Add(i, T, -val[i]), Add(T, i, 0);
Add(t, s, inf), Add(s, t, 0);
while (Bfs(S, T)) {
lep(i, 0, T) cur[i] = H[i];
Ans += Dfs(S, T, inf);
}
if (Ans != sum) Ans = -1;
H[s] = e[H[s]].n, H[t] = e[H[t]].n;
while (~Ans and Bfs(s, t)) {
lep(i, 0, t) cur[i] = H[i];
Ans += Dfs(s, t, inf);
}
if (pnt) puts(""); else pnt = true;
printf("%d\n", Ans);
return 0;
}
半平面交
bool Check(Line x, Node y) {
return Cmp(x.v * (y - x.p), 0) < 0;
}
int main() {
scanf("%d", & n);
lep(j, 1, n) {
scanf("%d", & m);
lep(i, 1, m) scanf("%lf%lf", & nd[i].x, & nd[i].y);
lep(i, 1, m) ln[++len] = Line(nd[i], nd[i % m + 1] - nd[i]);
}
std::sort(ln + 1, ln + 1 + len, [](Line x, Line y) {
db k1 = x.Getk(), k2 = y.Getk();
if (!Cmp(k1, k2)) return Check(x, y.p);
return k1 < k2;
});
n = 0;
lep(i, 1, len)
if (i == 1 or Cmp(ln[i].Getk(), ln[i - 1].Getk()) != 0)
ln[++n] = ln[i];
l = 1, r = 0;
lep(i, 1, n) {
while (l < r and Check(ln[i], nd[q[r]])) --r;
while (l < r and Check(ln[i], nd[q[l + 1]])) ++l;
q[++r] = i;
if (l < r) nd[i] = (ln[i] & ln[q[r - 1]]);
}
while (l + 2 < r and Check(-1 * ln[q[r]], ln[q[l]] & ln[q[r - 1]])) --r;
n = 0;
nd[q[l]] = (ln[q[r]] & ln[q[l]]);
lep(i, l, r) q[++n] = q[i];
lep(i, 1, n) ans += (nd[q[i]] * nd[q[i % n + 1]]) / 2;
printf("%.3lf\n", ans);
return 0;
}
旋转卡壳
db Gd(Poi p, Poi a, Poi b) { return ((p - a) * (b - a)) / (2 * (a % b)); }
void Insert(Poi x) {
while (top > len and (x - stk[top]) * (stk[top] - stk[top - 1]) <= 0) --top;
stk[++top] = x;
}
int main() {
scanf("%d", & n);
lep(i, 1, n) scanf("%lf%lf", & a[i].x, & a[i].y);
std::sort(a + 1, a + 1 + n, [](Poi a, Poi b) {
return a.x == b.x ? a.y < b.y : a.x < b.x; });
stk[++top] = a[1], len = 1;
lep(i, 2, n) Insert(a[i]);
len = top + 1;
rep(i, n - 1, 1) Insert(a[i]);
--top;
int pos = 1 % top + 1;
lep(i, 1, top) {
while (Gd(stk[pos % top + 1], stk[i], stk[i % top + 1]) >
Gd(stk[pos], stk[i], stk[i % top + 1])) pos = pos % top + 1;
ans = std::max(ans, stk[i] % stk[pos]),
ans = std::max(ans, stk[i % top + 1] % stk[pos]);
}
lep(i, 1, top) {
while (Gd(stk[pos % top + 1], stk[i], stk[i % top + 1]) >
Gd(stk[pos], stk[i], stk[i % top + 1])) pos = pos % top + 1;
ans = std::max(ans, stk[i] % stk[pos]),
ans = std::max(ans, stk[i % top + 1] % stk[pos]);
}
printf("%d\n", (int)ans);
return 0;
}
多项式开根(附二次剩余)
const int mod = 998244353;
const int g = 3;
struct Complex { ll r, c;
Complex(ll _r = 0, ll _c = 0) { r = _r, c = _c; }
friend Complex operator * (Complex A, Complex B) {
return Complex((A.r * B.r % mod + mod + (A.c * B.c % mod) * w % mod + mod) % mod, (A.r * B.c % mod + mod + A.c * B.r % mod + mod) % mod);
}
};
Complex MyCompPow(Complex A, ll B) {
Complex ans = Complex(1ll, 0ll);
for (; B; B >>= 1, A = A * A)
if (B & 1) ans = ans * A;
return ans;
}
ll Solve(ll n) {
ll a = rand() % mod;
while (MyPow(w = ((a * a - n) % mod + mod) % mod, (mod - 1) >> 1) == 1) a = rand() % mod;
Complex A(a, 1ll);
A = MyCompPow(A, (mod + 1) >> 1);
return std::min(A.r, mod - A.r);
}
const int inv_g = MyPow(3, mod - 2);
const int inv_2 = MyPow(2, mod - 2);
void NTT(ll a[], int n, int opt) {
int len = std::log2(n);
lep(i, 1, n - 1) if (i < rev[len][i]) std::swap(a[i], a[rev[len][i]]);
for (int w = 1; w < n; w <<= 1) {
for (int i = 0; i < n; i += (w << 1)) {
ll wk = 1, w1 = opt > 0 ? g : inv_g;
w1 = MyPow(w1, (mod - 1) / (w << 1));
lep(j, 0, w - 1)
b[i + j] = (a[i + j] + wk * a[i + j + w] % mod) % mod,
b[i + j + w] = (a[i + j] - wk * a[i + j + w] % mod) % mod,
wk = (wk * w1) % mod;
}
lep(i, 0, n - 1) a[i] = (b[i] + mod) % mod;
}
int inv = MyPow(n, mod - 2);
if (opt == -1) lep(i, 0, n - 1) a[i] = a[i] * inv % mod;
}
void Poly_Inv(ll a[], ll b[], int n) {
if (n == 1) { a[0] = MyPow(b[0], mod - 2); return; }
Poly_Inv(a, b, (n + 1) / 2);
int w = 1;
while (w < (n << 1)) w <<= 1;
lep(i, 0, n - 1) c[i] = b[i];
lep(i, n, w - 1) c[i] = 0;
NTT(a, w, 1), NTT(c, w, 1);
lep(i, 0, w - 1) a[i] = a[i] * (2 - a[i] * c[i] % mod) % mod;
NTT(a, w, -1);
lep(i, n, w - 1) a[i] = 0;
}
void Poly_Sqrt(ll a[], ll b[], int n) {
if (n == 1) { a[0] = Solve(b[0]); return; }
Poly_Sqrt(a, b, (n + 1) / 2);
Poly_Inv(inv, a, n);
int w = 1;
while (w < (n << 1)) w <<= 1;
lep(i, 0, n - 1) c[i] = b[i];
lep(i, n, w - 1) c[i] = 0;
NTT(a, w, 1), NTT(c, w, 1), NTT(inv, w, 1);
lep(i, 0, w - 1) a[i] = inv_2 * (a[i] + c[i] * inv[i] % mod) % mod;
NTT(a, w, -1);
lep(i, n, w - 1) a[i] = 0;
lep(i, 0, w - 1) inv[i] = 0;
}
杜教筛
ll GetPhi(int n) {
if (n < _) return phi[n];
if (Phi.count(n)) return Phi[n];
ll ans = 1ll * n * (n + 1ll) / 2;
ll l = 2, r = 2, tot;
while (l <= n) {
tot = n / l, r = n / tot;
ans -= (r - l + 1) * GetPhi(tot);
l = r + 1;
}
return Phi[n] = ans;
}
ll GetMob(int n) {
if (n < _) return mob[n];
if (Mob.count(n)) return Mob[n];
ll ans = 1;
ll l = 2, r = 2, tot;
while (l <= n) {
tot = n / l, r = n / tot;
ans -= (r - l + 1) * GetMob(tot);
l = r + 1;
}
return Mob[n] = ans;
}
int main() {
phi[1] = 1, mob[1] = 1;
lep(i, 2, _ - 1) {
if (!np[i]) p.push_back(i), phi[i] = i - 1, mob[i] = -1;
for (int j : p) if (1ll * i * j < _) {
np[i * j] = true;
if (i % j == 0) {
phi[i * j] = phi[i] * j,
mob[i * j] = 0; break;
}
phi[i * j] = phi[i] * phi[j],
mob[i * j] = -mob[i];
} else break;
}
lep(i, 2, _ - 1) phi[i] += phi[i - 1], mob[i] += mob[i - 1];
}
四边形不等式(单调队列)
ll w(int l, int r) {
int mid = (l + r) >> 1;
ll t1 = (mid - l) * a[mid] - (sum[mid - 1] - sum[l - 1]);
ll t2 = sum[r] - sum[mid] - (r - mid) * a[mid];
return t1 + t2;
}
ll Q(int k, int i) { return f[p ^ 1][k] + w(k + 1, i); }
int main() {
lep(j, 1, m) { p ^= 1;
l = 1, r = 0;
q[++r] = { 0, 1, n };
lep(i, 1, n) {
if (q[l].r < i) ++l; q[l].l = i;
f[p][i] = Q(q[l].x, i);
while (l <= r and Q(q[r].x, q[r].l) > Q(i, q[r].l)) --r;
int s, t = i;
if (l <= r) {
s = q[r].l, t = q[r].r + 1;
while (s < t) {
int mid = (s + t) >> 1;
if (Q(q[r].x, mid) > Q(i, mid)) t = mid;
else s = mid + 1;
}
q[r].r = t - 1;
}
q[++r] = { i, t, n };
}
}
}
LIS
void Insert(int x, int a[], int& len, int opt) {
if (x >= a[len] + opt) a[++len] = x;
else {
int pos = std::upper_bound(a + 1, a + 1 + len, x - opt) - a;
a[pos] = x;
}
}
int main() { b[0] = -inf;
while (scanf("%d", & x) == 1) {
Insert(-x, b, lenb, 0), Insert(x, c, lenc, 1);
}
printf("%d\n%d\n", lenb, lenc);
return 0;
}
斜率优化
LL X(int x) { return sum[x] + x; }
LL Y(int x) { return f[x] + (x + sum[x]) * (x + sum[x]); }
LL K(int x) { return 2 * (x + sum[x] - 1 - L); }
LL S(int x) { return (x + sum[x] - 1 - L) * (x + sum[x] - 1 - L); }
D G(PLL A, PLL B) {
if (A.second == B.second) return 0.0;
if (A.first == B.first) return A.second > B.second ? -inf : inf;
return D(B.second - A.second) / (B.first - A.first);
}
int main() {
scanf("%lld%lld", & N, & L);
lep(i, 1, N) scanf("%lld", C + i), sum[i] = sum[i - 1] + C[i];
stk[++top] = { X(0), Y(0) };
for (int i = 1; i <= N; ++i) {
LL k = K(i);
if (top == 1) f[i] = stk[top].second - k * stk[top].first + S(i);
else {
int l = 1, r = top;
while (l < r) {
int mid = (l + r + 1) >> 1;
if (k >= G(stk[mid - 1], stk[mid])) l = mid;
else r = mid - 1;
}
f[i] = stk[l].second - k * stk[l].first + S(i);
}
PLL A = { X(i), Y(i) };
while (top > 1 and G(stk[top - 1], stk[top]) > G(stk[top], A)) --top;
stk[++top] = A;
}
printf("%lld ", f[N]);
return 0;
}
//Luogu P3195
模拟退火
D C(D x0_, D y0_) {
D ans = 0;
lep(i, 1, n) ans += std::sqrt((x0_ - x[i]) * (x0_ - x[i]) + (y0_ - y[i]) * (y0_ - y[i])) * w[i];
return ans;
}
D S() { return T * (std::rand() * 2 - RAND_MAX); }
int main() {
std::srand(std::time(0));
scanf("%d", & n);
lep(i, 1, n) scanf("%d%d%d", x + i, y + i, w + i), x0_ += x[i], y0_ += y[i];
x0_ /= n, y0_ /= n; nw = Ans = C(x0_, y0_), xa = x0_, ya = y0_;
T = 100000, dl = 0.97;
while (T > 1e-15) {
D x1 = x0_ + S(), y1 = y0_ + S();
D tmp = C(x1, y1);
if (tmp < Ans) Ans = tmp, xa = x1, ya = y1;
if (tmp < nw or std::exp((nw - tmp) / T) > (D)std::rand() / RAND_MAX) nw = tmp, x0_ = x1, y0_ = y1;
T *= dl;
}
printf("%.3Lf %.3Lf\n", xa, ya);
return 0;
}
作者:qkhm
出处:https://www.cnblogs.com/qkhm/p/18494031/templete
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
时间仓促,如有错误欢迎指出,欢迎在评论区讨论,如对您有帮助还请点个推荐、关注支持一下
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
2023-10-22 CSP-J/S 2023 游记