模板整理

作者在多次程序爆炸后,痛定思痛,决定将各种算法和数据结构写法整理汇集成文。

数据结构

线段树


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 国际」许可协议进行许可。

posted @   qkhm  阅读(46)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
历史上的今天:
2023-10-22 CSP-J/S 2023 游记
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
点击右上角即可分享
微信分享提示