模板
AC
ケロシの代码
void build() {
queue<int> q;
REP(i, 26) {
if(tr[0][i]) q.push(tr[0][i]);
}
while(!q.empty()) {
int u = q.front();
q.pop();
REP(i, 26) {
if(tr[u][i]) {
fail[tr[u][i]] = tr[fail[u]][i];
q.push(tr[u][i]);
}
else {
tr[u][i] = tr[fail[u]][i];
}
}
}
}
SA
ケロシの代码
const int N = 1e6 + 5;
int n, m;
string s;
int sa[N], rk[N], a[N], tp[N];
void Sort() {
FOR(i, 1, m) a[i] = 0;
FOR(i, 1, n) a[rk[i]] ++;
FOR(i, 1, m) a[i] += a[i - 1];
ROF(i, n, 1) sa[a[rk[tp[i]]] --] = tp[i];
}
void SA() {
m = 130;
FOR(i, 1, n) rk[i] = s[i];
FOR(i, 1, n) tp[i] = i;
Sort();
for(int w = 1, p = 0; w <= n; m = p, p = 0, w <<= 1) {
FOR(i, n - w + 1, n) tp[++ p] = i;
FOR(i, 1, n) if(sa[i] > w) tp[++ p] = sa[i] - w;
Sort(); swap(rk, tp);
p = rk[sa[1]] = 1;
FOR(i, 2, n) rk[sa[i]] = (tp[sa[i]] == tp[sa[i - 1]] && tp[sa[i] + w] == tp[sa[i - 1] + w]) ? p : ++ p;
if(p == n) return;
}
}
SAM
ケロシの代码
const int N = 1e6 + 5;
struct node {
int len, link;
map<char, int> nxt;
} st[N << 1];
int sz, lst;
int n;
string s;
vector<int> e[N << 1];
ll ans, f[N << 1];
void dfs(int u) {
for(auto v : e[u]) {
dfs(v);
f[u] += f[v];
}
if(f[u] > 1) {
ans = max(ans, f[u] * st[u].len);
}
}
void sam_init() {
st[1].len = 0;
st[1].link = -1;
lst = sz = 1;
}
void sam_extend(char x) {
int cur = ++ sz;
f[cur] = 1;
st[cur].len = st[lst].len + 1;
int p = lst;
while(p != -1 && ! st[p].nxt.count(x)) {
st[p].nxt[x] = cur;
p = st[p].link;
}
if(p == -1) {
st[cur].link = 1;
}
else {
int q = st[p].nxt[x];
if(st[p].len + 1 == st[q].len) {
st[cur].link = q;
}
else {
int cln = ++sz;
st[cln].len = st[p].len + 1;
st[cln].nxt = st[q].nxt;
st[cln].link = st[q].link;
while(p != -1 && st[p].nxt[x] == q) {
st[p].nxt[x] = cln;
p = st[p].link;
}
st[q].link = st[cur].link = cln;
}
}
lst = cur;
}
void solve() {
cin >> s; n = s.size(); s = ' ' + s;
sam_init();
FOR(i, 1, n) sam_extend(s[i]);
FOR(i, 2, sz)
e[st[i].link].push_back(i);
dfs(1);
cout << ans << endl;
}
IO
ケロシの代码
namespace IO {
char buf[1024], * p1 = buf, * p2 = buf;
inline char gc() {
if(p1 == p2) {
p2 = buf + fread(buf, 1, sizeof buf, stdin);
p1 = buf;
}
return p1 == p2 ? EOF : * p1 ++;
}
int read() {
int res = 0; int v = 0;
char c = gc();
while(c < '0' || c > '9') {
if(c == '-') v = 1;
c = gc();
}
while('0' <= c && c <= '9') {
res = (res << 3) + (res << 1) + (c ^ 48);
c = gc();
}
return v ? - res : res;
}
}
using IO :: read;
Dinic
ケロシの代码
namespace Dinic {
const int N = 2e3 + 5;
const int M = 1e4 + 5;
const int INF = 0x3f3f3f3f;
struct Edge {
int ne, to, ew;
} e[M];
int fi[N], c[N], ecnt;
int S, T;
int d[N];
void init() {
memset(fi, 0, sizeof fi);
ecnt = 1;
}
void add(int u, int v, int w) {
e[++ ecnt] = {fi[u], v, w};
fi[u] = ecnt;
e[++ ecnt] = {fi[v], u, 0};
fi[v] = ecnt;
}
bool bfs() {
memset(d, 0x3f, sizeof d);
queue<int> q;
d[S] = 0; q.push(S);
while(! q.empty()) {
int u = q.front();
q.pop();
for(int i = fi[u]; i; i = e[i].ne) if(e[i].ew) {
int v = e[i].to;
if(d[v] == INF) {
d[v] = d[u] + 1;
q.push(v);
}
}
}
return d[T] != INF;
}
int dfs(int u, int w) {
if(u == T || ! w) return w;
int res = 0;
for(int & i = c[u]; i; i = e[i].ne) {
int v = e[i].to;
if(d[v] != d[u] + 1) continue;
int val = dfs(v, min(w, e[i].ew));
if(! val) continue;
e[i].ew -= val;
e[i ^ 1].ew += val;
res += val;
w -= val;
if(! w) return res;
}
return res;
}
int dinic(int _S, int _T) {
S = _S, T = _T;
int res = 0;
while(bfs()) {
memcpy(c, fi, sizeof c);
res += dfs(S, INF);
}
return res;
}
}
DET
ケロシの代码
int n, a[N][N];
int det() {
int res = 1, w = 1;
FOR(i, 1, n) {
FOR(j, i + 1, n) {
while(a[i][i]) {
int val = a[j][i] / a[i][i];
FOR(k, i, n) Sub(a[j][k], mul(val, a[i][k]));
swap(a[i], a[j]);
w = - w;
}
swap(a[i], a[j]);
w = - w;
}
}
FOR(i, 1, n) Mul(res, a[i][i]);
Mul(res, sub(w, 0));
return res;
}
杜教筛
ケロシの代码
ll get_phi(ll n) {
if(n < N) return sphi[n];
if(mphi.count(n)) return mphi[n];
ll res = n * (n + 1) / 2;
for(ll l = 2, r; l <= n; l = r + 1) {
r = n / (n / l);
res -= (r - l + 1) * get_phi(n / l);
}
return mphi[n] = res;
}
int get_mu(ll n) {
if(n < N) return smu[n];
if(mmu.count(n)) return mmu[n];
int res = 1;
for(ll l = 2, r; l <= n; l = r + 1) {
r = n / (n / l);
res -= (r - l + 1) * get_mu(n / l);
}
return mmu[n] = res;
}
类欧
ケロシの代码
ll F(ll a, ll b, ll c, ll n) {
ll res = n * (n + 1) / 2 * (a / c) + (n + 1) * (b / c);
a %= c, b %= c;
if(! a) return res;
ll m = (a * n + b) / c;
return res + n * m - F(c, c - b - 1, a, m - 1);
}
半平面交
ケロシの代码
const double EPS = 1e-10;
int dcmp(double x) {
if(fabs(x) < EPS) return 0;
if(x > 0) return 1;
return -1;
}
struct Point {
double x, y;
Point(double x = 0, double y = 0): x(x), y(y) {}
};
struct Vector {
double x, y;
Vector(double x = 0, double y = 0): x(x), y(y) {}
};
Vector operator + (Vector A, Vector B) {
return Vector(A.x + B.x, A.y + B.y);
}
Vector operator - (Vector A, Vector B) {
return Vector(A.x - B.x, A.y - B.y);
}
Vector operator - (Point A, Point B) {
return Vector(A.x - B.x, A.y - B.y);
}
Vector operator * (Vector A, double p) {
return Vector(A.x * p, A.y * p);
}
Vector operator / (Vector A, double p) {
return Vector(A.x / p, A.y / p);
}
Point operator + (Point A, Vector B) {
return Point(A.x + B.x, A.y + B.y);
}
Point operator - (Point A, Vector B) {
return Point(A.x - B.x, A.y - B.y);
}
bool operator == (const Point & A, const Point & B) {
return dcmp(A.x - B.x) == 0 && dcmp(A.y - B.y) == 0;
}
bool operator < (const Point & A,const Point & B) {
return dcmp(A.x - B.x) == 0 && A.y < B.y || A.x < B.x;
}
double Dot(Vector A, Vector B) {
return A.x * B.x + A.y * B.y;
}
double Length(Vector A) {
return sqrt(Dot(A, A));
}
double Angle(Vector A, Vector B) {
return acos(Dot(A, B) / Length(A) / Length(B));
}
double Cross(Vector A, Vector B) {
return A.x * B.y - A.y * B.x;
}
double Area(Point A, Point B, Point C) {
return Cross(B - A, C - A);
}
Vector Rotate(Vector A, double r) {
return Vector(A.x * cos(r) - A.y * sin(r), A.y * cos(r) + A.x * sin(r));
}
Vector Normal(Vector A) {
return Vector(- A.y / Length(A), A.x / Length(A));
}
Point GetLineInterSection(Point A,Vector B,Point C,Vector D) {
return A + B * (Cross(D, A - C) / Cross(B, D));
}
double DistanceToLine(Point A, Point B, Point C) {
return fabs(Cross(C - B, B - A) / Length(C - B));
}
double DistanceToSepment(Point A, Point B, Point C) {
if(B == C) return Length(A - B);
if(dcmp(Dot(C - B, A - B)) < 0) return Length(A - B);
if(dcmp(Dot(C - B, A - C)) > 0) return Length(A - C);
return fabs(Cross(C - B,A - B) / Length(C - B));
}
Point GetLineProjection(Point A, Point B, Point C) {
return B + (C - B) * Dot(C - B, A - B) / Dot(C - B, C - B);
}
bool SegmentProperIntersection(Point A1, Point A2, Point B1, Point B2) {
return dcmp(Cross(A2 - A1, B1 - A1)) * dcmp(Cross(A2 - A1, B2 - A1)) < 0
&& dcmp(Cross(B2 - B1, A1 - B1)) * dcmp(Cross(B2 - B1, A2 - B1)) < 0;
}
int ConvexHullAndrew(int n, Point * a, Point * b) {
sort(a + 1, a + n + 1);
int m = 0;
FOR(i, 1, n) {
while(m > 1 && Cross(b[m] - b[m - 1], a[i] - b[m - 1]) <= 0) m --;
b[++ m] = a[i];
}
int k = m;
ROF(i, n - 1, 1) {
while(m > k && Cross(b[m] - b[m - 1], a[i] - b[m - 1]) <= 0) m --;
b[++ m] = a[i];
}
if(n > 1) m --;
return m;
}
double RotatingCalipers(int n, Point * a) {
int j = 2;
double res = 0;
FOR(i, 1, n) {
while(Cross(a[i + 1] - a[i], a[j] - a[i]) < Cross(a[i + 1] - a[i], a[j + 1] - a[i])) j = j % n + 1;
chmax(res, max(Length(a[i] - a[j]), Length(a[i + 1] - a[j])));
}
return res;
}
double PolygonArea(int n, Point * a) {
double res = 0;
FOR(i, 2, n - 1) {
res += Cross(a[i] - a[1], a[i + 1] - a[1]);
}
return fabs(res) / 2;
}
double PolygonPass(Point s, Point t, int n, Point * a, Point * b, Point * c) {
bool ok = 1;
FOR(i, 1, n) if(SegmentProperIntersection(s, t, a[i], a[i % n + 1])) ok = 0;
if(ok) return Length(t - s);
int cnt = 2, m;
double ans1 = 0, ans2 = 0;
b[1] = s; b[2] = t;
FOR(i, 1, n) if(Cross(t - s,a[i] - s) > 0) b[++ cnt] = a[i];
m = ConvexHullAndrew(cnt, b, c);
FOR(i, 1, m) ans1 += Length(c[i] - c[i % m + 1]);
b[1] = s; b[2] = t;
cnt = 2;
FOR(i, 1, n) if(Cross(t - s,a[i] - s) < 0) b[++cnt] = a[i];
m = ConvexHullAndrew(cnt, b, c);
FOR(i, 1, m) ans2 += Length(c[i] - c[i % m + 1]);
return min(ans1, ans2) - Length(t - s);
}
int PolygonCut(int n, Point * a, Point * b, Point c, Point d) {
int res = 0;
FOR(i, 1, n) {
if(Cross(c - a[i],d - a[i]) >= 0){
b[++ res] = a[i];
if(Cross(c - a[i % n + 1], d - a[i % n + 1]) < 0)
b[++ res] = GetLineInterSection(a[i], a[i % n + 1] - a[i], c, d - c);
}
else if(Cross(c - a[i % n + 1], d - a[i % n + 1]) >= 0) {
b[++ res] = GetLineInterSection(a[i], a[i % n + 1] - a[i], c, d - c);
}
}
return res;
}
const int N = 1e5 + 5;
int n, m, k;
Point a[N], b[N], c[N];
void solve() {
cin >> n >> m;
FOR(i, 1, m) {
int x, y;
cin >> x >> y;
a[i] = Point(x, y);
}
REP(_, n - 1) {
cin >> k;
FOR(i, 1, k) {
int x, y;
cin >> x >> y;
b[i] = Point(x, y);
}
FOR(i, 1, k) {
m = PolygonCut(m, a, c, b[i], b[i % k + 1]);
FOR(j, 1, m) a[j] = c[j];
}
}
cout << fixed << setprecision(3);
cout << PolygonArea(m, a);
}
WBLT
点击查看代码
void rotate(int u, int o) {
if(!o) {
rs[u] = merge(rs[ls[u]], rs[u]);
ls[u] = ls[ls[u]];
}
else {
ls[u] = merge(ls[u], ls[rs[u]]);
rs[u] = rs[rs[u]];
}
}
void maintain(int u) {
if(sz[ls[u]] > sz[rs[u]] * 3) {
rotate(u, 0);
}
else if(sz[rs[u]] > sz[ls[u]] * 3) {
rotate(u, 1);
}
}
int merge(int u, int v) {
if(! u || ! v) return u | v;
if(sz[u] <= sz[v] * 4 && sz[v] <= sz[u] * 4) {
return up(u, v);
}
if(sz[u] >= sz[v]) {
down(u);
int l = ls[u], r = rs[u];
if(sz[l] * 4 >= (sz[u] + sz[v])) return merge(l, merge(r, v));
down(r);
return merge(merge(l, ls[r]), merge(rs[r], v));
}
else {
down(v);
int l = ls[v], r = rs[v];
if(sz[r] * 4 >= (sz[u] + sz[v])) return merge(merge(u, l), r);
down(l);
return merge(merge(u, ls[l]), merge(rs[l], r));
}
}