咕咕嘎嘎之傻九嘿嘿嘿
Fool
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128;
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
return 0;
}
图论
强连通分量缩点
struct SCC {
int n, dfncnt, cnt;
vector<int> stk;
vector<int> dfn, low, flag;
vector<vector<int>> e;
SCC() {}
SCC(int n) {
init(n);
}
void init(int n) {
this->n = n;
stk.clear();
dfn.assign(n, -1);
low.assign(n, -1);
flag.assign(n, -1);
e.assign(n, {});
dfncnt = cnt = 0;
}
void addedge(int u, int v) {
e[u].push_back(v);
}
void dfs(int u) {
stk.push_back(u);
dfn[u] = low[u] = dfncnt++;
for (auto v : e[u]) {
if (dfn[v] == -1) {
dfs(v);
low[u] = min(low[u], low[v]);
} else if (flag[v] == -1) {
low[u] = min(low[u], dfn[v]);
}
}
if (dfn[u] == low[u]) {
while (stk.back() != u) {
flag[stk.back()] = cnt;
stk.pop_back();
}
stk.pop_back();
flag[u] = cnt++;
}
}
vector<int> work() {
for (int i = 0; i < n; i++) {
if (dfn[i] == -1) {
dfs(i);
}
}
return flag;
}
};
点双
int dfncnt = 0;
vector<int> dfn(n + 1, 0), low(n + 1, 0);
stack<int> st;
vector<vector<int>> ans;
auto tarjan = [&](auto self, int u, int fa) -> void {
st.push(u);
dfn[u] = low[u] = ++dfncnt;
int son = 0;
for (auto v : e[u]) {
if (dfn[v] == 0) {
++son;
self(self, v, u);
low[u] = min(low[v], low[u]);
if (low[v] >= dfn[u]) {
vector<int> cur;
while (st.top() != v) {
cur.emplace_back(st.top()); //将同一个点双的点放进同一个vector
st.pop();
}
cur.emplace_back(v);
st.pop();
cur.emplace_back(u);
ans.emplace_back(cur);
}
} else if (v != fa) {
low[u] = min(low[u], dfn[v]); //对于点双,右边只能是dfn
}
}
if (fa == -1 && son == 0) {
vector<int> cur(1, u);
ans.emplace_back(cur);
}
};
for (int i = 1; i <= n; i++) {
if (dfn[i] == 0) {
while (!st.empty()) st.pop();
tarjan(tarjan, i, -1);
}
}
边双
int dfncnt = 0;
vector<int> dfn(n + 1, 0), low(n + 1, 0);
stack<int> st;
auto tarjan = [&](auto self, int u, int fa) -> void {
st.push(u);
dfn[u] = low[u] = ++dfncnt;
for (auto v : e[u]) {
if (dfn[v] == 0) {
self(self, v, u);
low[u] = min(low[u], low[v]);
} else if (v != fa) {
low[u] = min(low[u], dfn[v]);
}
}
if (dfn[u] == low[u]) {
while (st.top() != u) {
merge(st.top(), u); //将同一个边双的点合并
st.pop();
}
st.pop();
}
};
for (int i = 0; i <= n; i++) {
if (dfn[i] == 0) {
tarjan(tarjan, i, -1);
}
}
twosat
struct TwoSat {
int n;
vector<vector<int>> e;
vector<bool> ans;
TwoSat(int n) : n(n), e(2 * n), ans(n) {}
// u为true,或者v为true
// u(false)->v(true)
// v(false)->u(true)
void addedge(int u, bool a, int v, bool b) {
e[2 * u + !a].push_back(2 * v + b);
e[2 * v + !b].push_back(2 * u + a);
}
bool satisfible() {
int dfncnt = 0, cnt = 0;
vector<int> dfn(2 * n), low(2 * n), id(2 * n);
stack<int> stk;
auto tarjan = [&](auto self, int u) -> void {
stk.push(u);
dfn[u] = low[u] = ++dfncnt;
for (auto v : e[u]) {
if (dfn[v] == 0) {
self(self, v);
low[u] = min(low[u], low[v]);
} else if (id[v] == 0) {
low[u] = min(low[u], dfn[v]);
}
}
if (dfn[u] == low[u]) {
++cnt;
int v;
do {
v = stk.top();
stk.pop();
id[v] = cnt;
} while (v != u);
}
};
for (int i = 0; i < 2 * n; i++) {
if (dfn[i] == 0) {
tarjan(tarjan, i);
}
}
for (int i = 0; i < n; i++) {
if (id[2 * i] == id[2 * i | 1]) {
return false;
}
ans[i] = id[2 * i] > id[2 * i | 1];
}
return true;
}
vector<bool> answer() {
return ans;
}
};
最大流
using i64 = long long;
struct maxflow {
struct Edge {
int to;
i64 cap;
Edge(int to, i64 cap) : to(to), cap(cap) {}
};
int n;
vector<Edge> edges;
vector<vector<int>> e;
vector<int> cur, dep;
maxflow() {}
maxflow(int n) {
init(n);
}
void init(int n) {
this->n = n;
edges.clear();
e.assign(n, {});
cur.resize(n);
dep.resize(n);
}
bool bfs(int s, int t) {
dep.assign(n, 0); dep[s] = 1;
queue<int> q; q.push(s);
while (!q.empty()) {
const int u = q.front(); q.pop();
for (int i : e[u]) {
auto [v, c] = edges[i];
if (dep[v] == 0 && c > 0) {
dep[v] = dep[u] + 1;
if (v == t) {
return true;
}
q.push(v);
}
}
}
return false;
}
i64 dfs(int u, int t, i64 f) {
if (u == t || f == 0) {
return f;
}
i64 ret = 0;
for (int &i = cur[u]; i < int(e[u].size()); ++i) {
const int j = e[u][i];
auto [v, c] = edges[j];
if (c > 0 && dep[v] == dep[u] + 1) {
i64 k = dfs(v, t, min(f - ret, c));
edges[j].cap -= k;
edges[j ^ 1].cap += k;
ret += k;
if (ret == f) {
return f;
}
}
}
return ret;
}
void addedge(int u, int v, i64 c) {
e[u].push_back(edges.size());
edges.emplace_back(v, c);
e[v].push_back(edges.size());
edges.emplace_back(u, 0);
}
i64 flow(int s, int t) {
i64 ret = 0;
while (bfs(s, t)) {
cur.assign(n, 0);
ret += dfs(s, t, LONG_LONG_MAX);
}
return ret;
}
};
费用流
struct mcflow {
struct Edge {
int v, f, c;
Edge(int v, int f, int c) : v(v), f(f), c(c) {}
};
const int n;
vector<Edge> edges;
vector<vector<int>> e;
vector<i64> h, dis;
vector<int> pre;
mcflow(int n) : n(n), e(n) {}
void addedge(int u, int v, int f, int c) {
e[u].push_back(edges.size());
edges.emplace_back(v, f, c);
e[v].push_back(edges.size());
edges.emplace_back(u, 0, -c);
}
bool Dijstra(int s, int t) {
dis.assign(n, LONG_LONG_MAX);
pre.assign(n, -1);
priority_queue<pair<i64, int>, vector<pair<i64, int>>, greater<pair<i64, int>>> pq;
dis[s] = 0;
pq.emplace(0, s);
while (!pq.empty()) {
auto [d, u] = pq.top();
pq.pop();
if (dis[u] < d) {
continue;
}
for (int i : e[u]) {
auto [v, f, c] = edges[i];
if (f > 0 && dis[v] > d + h[u] - h[v] + c) {
dis[v] = d + h[u] - h[v] + c;
pre[v] = i;
pq.emplace(dis[v], v);
}
}
}
return dis[t] != LONG_LONG_MAX;
}
pair<int, i64> flow(int s, int t) {
int flow = 0;
i64 cost = 0;
h.assign(n, 0);
while (Dijstra(s, t)) {
for (int i = 0; i < n; i++) {
h[i] += dis[i];
}
int aug = INT_MAX;
for (int i = t; i != s; i = edges[pre[i] ^ 1].v) {
aug = min(aug, edges[pre[i]].f);
}
for (int i = t; i != s; i = edges[pre[i] ^ 1].v) {
edges[pre[i]].f -= aug;
edges[pre[i] ^ 1].f += aug;
}
flow += aug;
cost += i64(aug) * h[t];
}
return make_pair(flow, cost);
}
};
树剖
vector<int> dep(n, 0), siz(n, 0), fa(n, 0), hson(n, -1);
auto dfs1 = [&](auto self, int u) -> void {
siz[u] = 1;
for (auto v : e[u]) {
if (v == fa[u]) {
continue;
}
fa[v] = u;
dep[v] = dep[u] + 1;
self(self, v);
siz[u] += siz[v];
if (hson[u] == -1 || siz[v] > siz[hson[u]]) {
hson[u] = v;
}
}
};
int dfncnt = 0;
vector<int> dfn(n, -1), top(n, 0), rank(n + 1, 0), bot(n, -1);
auto dfs2 = [&](auto self, int u, int t) -> void {
top[u] = t;
dfn[u] = ++dfncnt;
rank[dfncnt] = u;
if (hson[u] != -1) {
self(self, hson[u], t);
}
for (auto v : e[u]) {
if (v == fa[u] || v == hson[u]) {
continue;
}
self(self, v, v);
}
bot[u] = dfncnt;
};
虚树
看个大概
auto g = e;
vector<int> flag(n, 0);
for (int q = 1; q <= Q; q++) {
int m;
cin >> m;
vector<int> a(m);
for (int i = 0; i < m; i++) {
cin >> a[i];
a[i]--;
flag[a[i]] = q;
}
sort(a.begin(), a.end(), [&](int u, int v) -> bool { return dfn[u] < dfn[v]; });
stack<int> stk;
stk.push(0);
g[0].clear();
for (auto u : a) {
int p = lca(u, stk.top());
if (p != stk.top()) {
int v = stk.top();
stk.pop();
while (dfn[stk.top()] > dfn[p]) {
g[stk.top()].emplace_back(v);
v = stk.top();
stk.pop();
}
if (dfn[stk.top()] != dfn[p]) {
g[p].clear();
stk.push(p);
}
g[stk.top()].emplace_back(v);
}
stk.push(u);
g[u].clear();
}
int cur = stk.top();
stk.pop();
while (!stk.empty()) {
g[stk.top()].emplace_back(cur);
cur = stk.top();
stk.pop();
}
}
树分治
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
using u64 = unsigned long long;
struct Edge {
int u, v, w;
};
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<Edge> edg(n - 1);
vector<vector<int>> e(n);
for (int i = 0; i < n - 1; i++) {
int u, v, w;
cin >> u >> v >> w;
u--;
v--;
edg[i].u = u;
edg[i].v = v;
edg[i].w = w;
e[u].push_back(i);
e[v].push_back(i);
}
vector<int> siz(n), vis(n), dis(n);
auto init = [&]() -> void {
};
auto dfs1 = [&](auto self, int u, int p) -> void {
siz[u] = 1;
for (auto i : e[u]) {
int v = u ^ edg[i].u ^ edg[i].v;
if (v == p || vis[v]) {
continue;
}
self(self, v, u);
siz[u] += siz[v];
}
};
auto find = [&](auto self, int u, int p, int rt) -> int {
for (auto i : e[u]) {
int v = u ^ edg[i].u ^ edg[i].v;
if (v == p || vis[v]) {
continue;
}
if (2 * siz[v] >= siz[rt]) {
return self(self, v, u, rt);
}
}
return u;
};
auto dfs2 = [&](auto self, int u, int p) -> void {
// ???
for (auto i : e[u]) {
int v = u ^ edg[i].u ^ edg[i].v;
if (v == p || vis[v]) {
continue;
}
dis[v] = dis[u] + edg[i].w;
self(self, v, u);
}
};
queue<int> q;
q.push(0);
int ans = 0;
while (!q.empty()) {
auto u = q.front();
q.pop();
dfs1(dfs1, u, u);
u = find(find, u, u, u);
init();
dis[u] = 0;
// ???
vis[u] = 1;
for (auto i : e[u]) {
int v = u ^ edg[i].u ^ edg[i].v;
if (vis[v]) {
continue;
}
q.push(v);
}
}
return 0;
}
树hash
const int N = 1e6;
const u64 seed = mt19937_64(time(nullptr))();
vector<u64> Hash(N);
vector<vector<int>> e(N);
u64 shift(u64 x) {
x ^= x << 13;
x ^= x >> 7;
x ^= x << 17;
return x;
}
void dfs(int u, int p) {
Hash[u] = 1;
for (auto v : e[u]) {
if (v == p) {
continue;
}
dfs(v, u);
Hash[u] += shift(Hash[v]);
}
}
数论
线性筛
vector<int> minp, primes;
void sieve(int n) {
minp.assign(n + 1, 0);
primes.clear();
for (int i = 2; i <= n; i++) {
if (minp[i] == 0) {
minp[i] = i;
primes.push_back(i);
}
for (auto p : primes) {
if (i * p > n) {
break;
}
minp[i * p] = p;
if (p == minp[i]) {
break;
}
}
}
}
/*
*********************************************
*/
vector<int> minp, primes, phi;
void sieve(int n) {
primes.clear();
phi.assign(n + 1, 0);
minp.assign(n + 1, 0);
phi[1] = 1;
for (int i = 2; i <= n; i++) {
if (minp[i] == 0) {
minp[i] = i;
phi[i] = i - 1;
primes.push_back(i);
}
for (auto p : primes) {
if (i * p > n) {
break;
}
minp[i * p] = p;
if (p == minp[i]) {
phi[i * p] = phi[i] * p;
break;
}
phi[i * p] = phi[i] * (p - 1);
}
}
}
/*
*********************************************
*/
vector<int> minp, primes, mu;
void sieve(int n) {
minp.assign(n + 1, 0);
mu.assign(n + 1, 0);
primes.clear();
mu[1] = 1;
for (int i = 2; i <= n; i++) {
if (minp[i] == 0) {
minp[i] = i;
mu[i] = -1;
primes.push_back(i);
}
for (auto p : primes) {
if (i * p > n) {
break;
}
minp[i * p] = p;
if (p == minp[i]) {
break;
}
mu[i * p] = -mu[i];
}
}
}
/*
*********************************************
*/
// 和函数, o(nloglogn)
for (int i = 1; i <= n; i++) {
F[i] = f[i];
}
for (auto p : primes) {
for (int i = 1; i * p <= n; i++) {
F[i * p] += f[i];
}
}
杜教筛
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
using u64 = unsigned long long;
const int N = 1000000;
vector<int> minp, primes, phi, mu;
void sieve(int n) {
minp.assign(n + 1, 0);
phi.assign(n + 1, 0);
mu.assign(n + 1, 0);
primes.clear();
phi[1] = mu[1] = 1;
for (int i = 2; i <= n; i++) {
if (minp[i] == 0) {
minp[i] = i;
phi[i] = i - 1;
mu[i] = -1;
primes.push_back(i);
}
for (auto p : primes) {
if (i * p > n) {
break;
}
minp[i * p] = p;
if (p == minp[i]) {
phi[i * p] = phi[i] * p;
break;
}
phi[i * p] = phi[i] * (p - 1);
mu[i * p] = -mu[i];
}
}
}
vector<i64> pre_mu, pre_phi;
unordered_map<i64, i64> fMu, fPhi;
i64 get_mu(i64 n) {
if (n <= i64(N)) {
return pre_mu[n];
}
if (fMu.count(n)) {
return fMu[n];
}
i64 ret = 1;
for (i64 L = 2, R; L <= n; L = R + 1) {
R = n / (n / L);
ret -= 1LL * (R - L + 1) * get_mu(n / L);
}
fMu[n] = ret;
return ret;
}
i64 get_phi(i64 n) {
if (n <= i64(N)) {
return pre_phi[n];
}
if (fPhi.count(n)) {
return fPhi[n];
}
i64 ret = 1LL * n * (n + 1) / 2;
for (i64 L = 2, R; L <= n; L = R + 1) {
R = n / (n / L);
ret -= 1LL * (R - L + 1) * get_phi(n / L);
}
fPhi[n] = ret;
return ret;
}
void solve() {
i64 n;
cin >> n;
cout << get_phi(n) << " " << get_mu(n) << "\n";
}
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
sieve(N);
pre_mu.assign(N + 1, 0);
pre_phi.assign(N + 1, 0);
for (int i = 1; i <= N; i++) {
pre_mu[i] = pre_mu[i - 1] + mu[i];
pre_phi[i] = pre_phi[i - 1] + phi[i];
}
solve();
return 0;
}
求单个欧拉函数
int phi(int x) {
int ret = x;
for (int i = 2; i * i <= x; i++) {
if (x % i == 0) {
while (x % i == 0) {
x /= i;
}
ret = ret / i * (i - 1);
}
}
if (x > 1) {
ret = ret / x * (x - 1);
}
return ret;
}
素性测试与因式分解
i64 Mul(i64 x, i64 y, i64 mod) {
return static_cast<__int128>(x) * y % mod;
}
i64 power(i64 x, i64 n, i64 mod) {
i64 ret = 1;
while (n > 0LL) {
if (n & 1) {
ret = Mul(ret, x, mod);
}
n >>= 1;
x = Mul(x, x, mod);
}
return ret;
}
// 素数返回true
bool isprime(i64 x) {
vector<i64> test = { 2,3,5,7,11,13,17,19,23,29,31,37 };
if (x <= 40LL) {
for (auto y : test) {
if (x == y) {
return true;
}
}
return false;
}
int v = __builtin_ctzll(x - 1);
i64 u = (x - 1) >> v;
for (auto y : test) {
i64 z = power(y, u, x);
for (int i = 0; i < v; i++) {
i64 nz = Mul(z, z, x);
if (nz == 1 && z != 1 && z != x - 1) {
return false;
}
z = nz;
}
if (z != 1) {
return false;
}
}
return true;
}
vector<i64> factorize(i64 n) {
vector<i64> ret;
auto f = [&](auto self, i64 z) -> void {
if (isprime(z)) {
ret.push_back(z);
return;
}
i64 p = z;
while (p >= z) {
i64 i = 1, k = 2;
i64 c = rand() % (p - 1) + 1;
i64 x = rand() % p;
i64 y = x;
while (true) {
i++;
x = (Mul(x, x, p) + c) % p;
i64 d = gcd(abs(x - y), p);
if (d != 1 && d != p) {
p = d;
break;
}
if (y == x) {
break;
}
if (i == k) {
y = x;
k <<= 1;
}
}
}
self(self, p);
self(self, z / p);
};
f(f, n);
sort(ret.begin(), ret.end());
return ret;
}
不可靠的fft
constexpr double Pi = 3.1415926535897;
vector<int> rev;
struct Complex {
double x, y;
Complex() {}
Complex(double x, double y) : x(x), y(y) {}
Complex operator + (Complex B) {
return Complex(x + B.x, y + B.y);
}
Complex operator - (Complex B) {
return Complex(x - B.x, y - B.y);
}
Complex operator * (Complex B) {
return Complex(x * B.x - y * B.y, x * B.y + y * B.x);
}
};
void FFT(vector<Complex> &A) {
int n = int(A.size());
for (int i = 0; i < n; i++) {
if (i < rev[i]) {
swap(A[i], A[rev[i]]);
}
}
for (int i = 1; i < n; i <<= 1) {
auto W = Complex(cos(Pi / i), sin(Pi / i));
for (int j = 0; j < n; j += (i << 1)) {
auto w = Complex(1.0, 0.0);
for (int k = 0; k < i; k++, w = w * W) {
auto x = A[j + k], y = w * A[j + k + i];
A[j + k] = x + y;
A[j + k + i] = x - y;
}
}
}
}
void IFFT(vector<Complex> &A) {
FFT(A);
reverse(A.begin() + 1, A.end());
}
vector<i64> Mul(vector<i64> a, vector<i64> b) {
int N = int(a.size()), M = int(b.size());
int n = 1, bit = 0, tot = N + M - 1;
while (n < tot) {
bit++;
n <<= 1;
}
if (tot < 1024) {
vector<i64> c(tot);
for (int i = 0; i < int(a.size()); i++) {
for (int j = 0; j < int(b.size()); j++) {
c[i + j] = c[i + j] + 1LL * a[i] * b[j];
}
}
return c;
}
vector<Complex> A(n), B(n);
for (int i = 0; i < N; i++) {
A[i] = Complex(a[i], 0);
}
for (int i = 0; i < M; i++) {
B[i] = Complex(b[i], 0);
}
rev.resize(n);
for (int i = 0; i < n; i++) {
rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (bit - 1));
}
FFT(A), FFT(B);
for (int i = 0; i < n; i++) {
A[i] = A[i] * B[i];
}
IFFT(A);
a.resize(tot);
for (int i = 0; i < tot; i++) {
a[i] = i64(A[i].x / n + 0.5);
}
return a;
}
NTT
constexpr int P = 998244353;
int power(int a, int b) {
int res = 1;
for (; b; b /= 2, a = 1LL * a * a % P) {
if (b % 2) {
res = 1LL * res * a % P;
}
}
return res;
}
vector<int> rev, roots;
void dft(vector<int> &a) {
int n = a.size();
if (int(rev.size()) != n) {
int k = __builtin_ctz(n) - 1;
rev.resize(n);
for (int i = 0; i < n; i++) {
rev[i] = rev[i >> 1] >> 1 | (i & 1) << k;
}
}
for (int i = 0; i < n; i++) {
if (rev[i] < i) {
swap(a[i], a[rev[i]]);
}
}
if (roots.size() < n) {
int k = __builtin_ctz(roots.size());
roots.resize(n);
while ((1 << k) < n) {
int e = power(31, 1 << (__builtin_ctz(P - 1) - k - 1));
for (int i = 1 << (k - 1); i < (1 << k); i++) {
roots[2 * i] = roots[i];
roots[2 * i + 1] = 1LL * roots[i] * e % P;
}
k++;
}
}
for (int k = 1; k < n; k *= 2) {
for (int i = 0; i < n; i += 2 * k) {
for (int j = 0; j < k; j++) {
int u = a[i + j];
int v = 1LL * a[i + j + k] * roots[k + j] % P;
a[i + j] = (u + v) % P;
a[i + j + k] = ((u - v) % P + P) % P;
}
}
}
}
void idft(vector<int> &a) {
int n = a.size();
reverse(a.begin() + 1, a.end());
dft(a);
int inv = power(n, P - 2);
for (int i = 0; i < n; i++) {
a[i] = 1LL * a[i] * inv % P;
}
}
vector<int> mul(vector<int> a, vector<int> b) {
rev.clear();
roots = {0, 1};
int n = 1, tot = a.size() + b.size() - 1;
while (n < tot) {
n *= 2;
}
if (tot < 128) {
vector<int> c(a.size() + b.size() - 1);
for (int i = 0; i < a.size(); i++) {
for (int j = 0; j < b.size(); j++) {
c[i + j] = (c[i + j] + 1LL * a[i] * b[j]) % P;
}
}
return c;
}
a.resize(n);
b.resize(n);
dft(a);
dft(b);
for (int i = 0; i < n; i++) {
a[i] = 1LL * a[i] * b[i] % P;
}
idft(a);
a.resize(tot);
return a;
}
几何
凹包, 旋转卡壳
struct Point {
i64 x, y;
Point() {}
Point(i64 x, i64 y) : x(x), y(y) {}
Point operator + (Point B) {
return Point(x + B.x, y + B.y);
}
Point operator - (Point B) {
return Point(x - B.x, y - B.y);
}
bool operator == (Point B) const {
return x == B.x && y == B.y;
}
bool operator < (Point B) const {
return x < B.x || (x == B.x && y < B.y);
}
};
typedef Point Vector;
// 点乘
i64 dot(const Vector &A, const Vector &B) {
return A.x * B.x + A.y * B.y;
}
// 叉乘
i64 cross(const Vector &A, const Vector &B) {
return A.x * B.y - A.y * B.x;
}
// 距离
double distance(const Point &A, const Point &B) {
return hypot(A.x - B.x, A.y - B.y);
}
// 距离的平方
i64 dis_double(const Point &A, const Point &B) {
return (A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y);
}
// 面积
i64 getarea(Vector A, Vector B) {
return llabs(cross(A, B));
}
vector<Point> getHull(vector<Point> p) {
sort(p.begin(), p.end());
p.erase(unique(p.begin(), p.end()), p.end());
if (p.size() <= 1) {
return p;
}
vector<Point> h, l;
for (auto a : p) {
while (h.size() > 1 && cross(a - h.back(), a - h[h.size() - 2]) <= 0) {
h.pop_back();
}
while (l.size() > 1 && cross(a - l.back(), a - l[l.size() - 2]) >= 0) {
l.pop_back();
}
h.push_back(a);
l.push_back(a);
}
l.pop_back();
reverse(h.begin(), h.end());
h.pop_back();
l.insert(l.end(), h.begin(), h.end());
return l;
}
// 直径的平方
i64 getlongest(vector<Point> p) {
p.push_back(p.front());
if (p.size() < 4) {
return dis_double(p[0], p[1]);
}
i64 ret = 0;
for (int i = 1, j = 2, n = p.size(); i < p.size(); i++) {
while (getarea(p[i] - p[i - 1], p[j] - p[i - 1]) <= getarea(p[i] - p[i - 1], p[(j + 1) % n] - p[i - 1])) {
j = (j + 1) % n;
}
ret = max({ret, dis_double(p[j], p[i - 1]), dis_double(p[j], p[i])});
}
return ret;
}
疑点重重的半平面交
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
const double Pi = acos(-1.0);
const double eps = 1e-8;
int sgn(double x) {
if (fabs(x) <= eps) return 0;
return x > 0 ? 1 : -1;
}
int dcmp(double x, double y) {
if (fabs(x - y) <= eps) return 0;
return x - y > 0 ? 1 : -1;
}
struct Point {
double x, y;
Point() {}
Point(double x, double y) : x(x), y(y) {}
Point operator + (Point B) {
return Point(x + B.x, y + B.y);
}
Point operator - (Point B) {
return Point(x - B.x, y - B.y);
}
Point operator * (double k) {
return Point(x * k, y * k);
}
Point operator / (double k) {
return Point(x / k, y / k);
}
bool operator == (const Point &B) const {
return sgn(x - B.x) == 0 && sgn(y - B.y) == 0;
}
bool operator < (const Point &B) const {
return sgn(x - B.x) < 0 || (sgn(x - B.x) == 0 && sgn(y - B.y) < 0);
}
};
typedef Point Vector;
double Distance(const Point &A, const Point &B) {
return hypot(A.x - B.x, A.y - B.y);
}
double Dot(const Vector &A, const Vector &B) {
return A.x * B.x + A.y * B.y;
}
double Len(const Vector &A) {
return sqrt(Dot(A, A));
}
double Cross(const Vector &A, const Vector &B) {
return A.x * B.y - A.y * B.x;
}
double Area2(Point A, Point B, Point C) {
return Cross(B - A, C - A);
}
// 逆时针旋转rad
Vector Rotate(const Vector &A, double rad) {
return Vector(A.x * cos(rad) - A.y * sin(rad), A.x * sin(rad) + A.y * cos(rad));
}
// 逆时针旋转90度
Vector Rotate2(const Vector &A) {
return Vector(-A.y, A.x);
}
// 检查两个向量是否平行
bool Parallel(const Vector &A, const Vector &B) {
return sgn(Cross(A, B)) == 0;
}
struct Line {
Point p;
Vector v;
double ang;
Line() {}
Line(Point p, Vector v) : p(p), v(v) { ang = atan2(v.y, v.x); }
bool operator < (const Line &B) const {
return ang < B.ang;
}
};
bool Onleft(const Line &L, Point p) {
return sgn(Cross(L.v, p - L.p)) > 0;
}
Point Cross_point(Line A, Line B) {
Vector u = A.p - B.p;
double t = Cross(B.v, u) / Cross(A.v, B.v);
return A.p + A.v * t;
}
vector<Point> HPI(vector<Line> L) {
const int n = L.size();
sort(L.begin(), L.end());
deque<Line> l;
deque<Point> p;
l.emplace_back(L[0]);
for (int i = 1; i < n; i++) {
while (p.size() > 0 && !Onleft(L[i], p.back())) {
p.pop_back();
l.pop_back();
}
while (p.size() > 0 && !Onleft(L[i], p.front())) {
p.pop_front();
l.pop_front();
}
if (sgn(Cross(L[i].v, l.back().v)) == 0) {
if (Onleft(l.back(), L[i].p)) {
l.pop_back();
if (l.size() > 0) {
p.pop_back();
p.emplace_back(Cross_point(L[i], l.back()));
}
l.emplace_back(L[i]);
}
} else {
p.emplace_back(Cross_point(L[i], l.back()));
l.emplace_back(L[i]);
}
}
while (p.size() > 0 && !Onleft(l.front(), p.back())) {
l.pop_back();
p.pop_back();
}
vector<Point> ret;
if (l.size() <= 2) {
return ret;
}
p.emplace_back(Cross_point(l.front(), l.back()));
for (auto x : p) {
ret.emplace_back(x);
}
return ret;
}
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<Line> L;
while (n--) {
int m;
cin >> m;
vector<int> x(m + 1), y(m + 1);
for (int i = 0; i < m; i++) {
cin >> x[i] >> y[i];
}
x[m] = x[0], y[m] = y[0];
for (int i = 0; i < m; i++) {
L.emplace_back(Line(Point(x[i], y[i]), Vector(x[i + 1] - x[i], y[i + 1] - y[i])));
}
}
auto Hull = HPI(L);
double ans = 0;
for (int i = 2; i < Hull.size(); i++) {
ans += Cross(Hull[i - 1] - Hull.front(), Hull[i] - Hull.front()) / 2;
}
printf("%.3f\n", ans);
return 0;
}
完全正确的平面最近点对
#include <bits/stdc++.h>
using namespace std;
const double eps = 1e-8;
const double inf = 1e20;
struct Point {
double x, y;
Point() {}
Point(double x, double y) : x(x), y(y) {}
};
int sgn(double x) {
if (fabs(x) < eps) return 0;
return x < 0 ? -1 : 1;
}
double distance(Point A, Point B) {
return hypot(A.x - B.x, A.y - B.y);
}
bool cmpxy(Point A, Point B) {
return sgn(A.x - B.x) < 0 || (sgn(A.x - B.x) == 0 && sgn(A.y - B.y) < 0);
}
bool cmpy(Point A, Point B) {
return sgn(A.y - B.y) < 0;
}
double closest_pair(vector<Point> &p, int l, int r) {
double dis = inf;
if (l == r) return dis;
if (l + 1 == r) return distance(p[l], p[r]);
int mid = (l + r) >> 1;
dis = min(closest_pair(p, l, mid), closest_pair(p, mid + 1, r));
vector<Point> tmp;
for (int i = l; i <= r; i++) {
if (fabs(p[mid].x - p[i].x) <= dis) {
tmp.emplace_back(p[i]);
}
}
sort(tmp.begin(), tmp.end(), cmpy);
for (int i = 0; i < tmp.size(); i++) {
for (int j = i + 1; j < tmp.size(); j++) {
if (tmp[j].y - tmp[i].y >= dis) break;
dis = min(dis, distance(tmp[i], tmp[j]));
}
}
return dis;
}
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<Point> p(n);
for (int i = 0; i < n; i++) {
cin >> p[i].x >> p[i].y;
}
sort(p.begin(), p.end(), cmpxy);
double ans = closest_pair(p, 0, n - 1);
printf("%.4f\n", ans);
return 0;
}
数据结构
最爱的dsu
struct DSU {
vector<int> f, siz;
DSU() {}
DSU(int n) {
init(n);
}
void init(int n) {
f.resize(n);
iota(f.begin(), f.end(), 0);
siz.assign(n, 1);
}
int find(int x) {
while (f[x] != x) {
x = f[x] = f[f[x]];
}
return x;
}
bool merge(int x, int y) {
x = find(x);
y = find(y);
if (x == y) {
return false;
}
siz[x] += siz[y];
f[y] = x;
return true;
}
int size(int x) {
return siz[find(x)];
}
bool same(int x, int y) {
return find(x) == find(y);
}
};
可撤销dsu
struct DSU {
vector<int> f, siz;
vector<array<int, 2>> his;
DSU() {}
DSU(int n) : siz(n, 1), f(n) {
iota(f.begin(), f.end(), 0);
}
int find(int x) {
while (f[x] != x) {
x = f[x];
}
return x;
}
bool merge(int x, int y) {
x = find(x);
y = find(y);
if (x == y) {
return false;
}
if (siz[x] < siz[y]) {
swap(x, y);
}
his.push_back({x, y});
siz[x] += siz[y];
f[y] = x;
return true;
}
int time() {
return his.size();
}
void revert(int tim) {
while (his.size() > tim) {
auto [x, y] = his.back();
his.pop_back();
f[y] = y;
siz[x] -= siz[y];
}
}
};
Fenwick
struct Fenwick {
int n;
vector<i64> f;
Fenwick() {}
Fenwick(int n) {
init(n);
}
void init(int n) {
this->n = n;
f.assign(n + 1, 0);
}
void add(int k, i64 x) {
while (k <= n) {
f[k] += x;
k += k & -k;
}
}
i64 sum(int k) {
i64 ret = 0;
while (k > 0) {
ret += f[k];
k -= k & -k;
}
return ret;
}
i64 sum(int l, int r) {
return sum(r) - sum(l - 1);
}
void update(int id, i64 x) {
add(id, x);
add(id + 1, -x);
}
void update(int l, int r, i64 x) {
add(l, x);
add(r + 1, -x);
}
i64 query(int id) {
return sum(id);
}
};
新鲜出炉的哥哥笛卡尔
vector<int> lc(n + 1, 0), rc(n + 1, 0), stk;
for (int i = 1; i <= n; i++) {
while (!stk.empty() && w[i] < w[stk.back()]) {
rc[stk.back()] = lc[i];
lc[i] = stk.back();
stk.pop_back();
}
stk.push_back(i);
}
while (stk.size() > 1) {
int x = stk.back();
stk.pop_back();
rc[stk.back()] = x;
}
字符串
KMP
vector<int> prefix_function(string s) {
int n = s.length();
vector<int> pi(n);
for (int i = 1; i < n; i++) {
int j = pi[i - 1];
while (j > 0 && s[i] != s[j]) j = pi[j - 1];
if (s[i] == s[j]) j++;
pi[i] = j;
}
return pi;
}
vector<int> KMP(string find, string s) {
string cur = find + "#" + s;
int siz1 = find.length(), siz2 = s.length();
vector<int> v;
vector<int> lps = prefix_function(cur);
for (int i = siz1 + 1; i <= siz1 + siz2; i++) {
if (lps[i] == siz1) v.push_back(i - 2 * siz1);
}
return v;
}
ZZZZZ
vector<int> z_function(string s) {
int n = s.length();
vector<int> z(n);
for (int i = 1, l = 0, r = 0; i < n; i++) {
if (i <= r && z[i - l] < r - i + 1) {
z[i] = z[i - l];
} else {
z[i] = max(0, r - i + 1);
while (i + z[i] < n && s[z[i]] == s[i + z[i]]) ++z[i];
}
if (i + z[i] - 1 > r) l = i, r = i + z[i] - 1;
}
return z;
}
距今10000年前写的aczdj
#include <bits/stdc++.h>
using namespace std;
const int maxn = 5e5 + 10;
int pos = 0;
int trie[maxn][26], num[maxn];
int fail[maxn];
int indegree[maxn], lazy[maxn];
string s[maxn];
int mp[maxn];
void trie_insert(string s, int idx) {
int p = 0;
for (auto c : s) {
int n = c - 'a';
if (trie[p][n] == 0) {
trie[p][n] = ++pos;
}
p = trie[p][n];
}
mp[idx] = p;
}
void get_fail() {
queue<int> q;
for (int i = 0; i < 26; i++) {
if (trie[0][i]) {
q.push(trie[0][i]);
}
}
while (!q.empty()) {
int u = q.front();
q.pop();
for (int i = 0; i < 26; i++) {
if (trie[u][i]) {
fail[trie[u][i]] = trie[fail[u]][i];
indegree[fail[trie[u][i]]]++;
q.push(trie[u][i]);
} else {
trie[u][i] = trie[fail[u]][i];
}
}
}
}
void query(string s) {
int u = 0, res = 0;
for (int i = 0; i < s.length(); i++) {
u = trie[u][s[i] - 'a'];
lazy[u]++;
}
}
void topsort() {
queue<int> q;
for (int i = 1; i <= pos; i++) {
if (!indegree[i]) q.push(i);
}
while (!q.empty()) {
int u = q.front();
q.pop();
num[u] = lazy[u];
int v = fail[u];
lazy[v] += lazy[u];
if (!(--indegree[v])) q.push(v);
}
}
void solve() {
int n;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> s[i];
trie_insert(s[i], i);
}
get_fail();
string T;
cin >> T;
query(T);
topsort();
for (int i = 0; i < n; i++) {
cout << num[mp[i]] << endl;
}
}

浙公网安备 33010602011771号