Template
DoctorBobo · · 个人记录
1. 头部&宏定义
#include<bits/stdc++.h>
#define rg register
#define For(i, a, b) for(int (i) = (a); (i) <= (b); (i)++)
#define FOR(i, a, b) for(int (i) = (a); (i) >= (b); (i)--)
#define acl() ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define fix(i) cout << fixed << setprecision(i)
#define pb push_back
#define lson (p << 1)
#define rson (p << 1 | 1)
using namespace std;
using i64 = long long;
using d64 = long double;
using pii = std::pair<int, int>;
using pll = std::pair<i64, i64>;
inline int read(){
int x = 0, f = 0;
char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = 1;
c = getchar();
}
while(c >= '0' && c <= '9') {
x = (x << 3) + (x << 1) + c - 48;
c = getchar();
}
return f ? -x : x;
}
void solve();
int main() {
acl();
int t = 1;
//cin >> t;
while(t--) solve();
return 0;
}
2.链式前行星建边和删边
struct Edge {int nxt, to, w, *from;};
cin >> n >> m; tot = 1;//tot starts from 2
std::vector<Edge> e(m * 2 + 2);
std::vector<int> head(n + 1, 0);
auto add_edge = [&](int u, int v, int w)->void {
e[++tot] = {head[u], v, w, &head[u]};
if(head[u]) e[head[u]].from = &e[tot].nxt;
head[u] = tot;
};
auto dlt_edge = [&](int u)->void {
*e[u].from = e[u].nxt;
if(e[u].nxt) e[e[u].nxt].from = e[u].from;
e[u].from = NULL;
};
3.用链式前向星跑欧拉回路(存在欧拉回路)
std::vector<int> st, head(n + 1, 0);
auto Euler = [&](auto self, int u)->void {
for(int i = head[u]; e[i].from != NULL; i = head[u]) {
head[u] = e[i].nxt;
int v = e[i].to;
dlt_edge(i), dlt_edge(i ^ 1);
self(self, v);
} st.pb(u);
//self loop : while(sum[u]) st.pb(u), sum[u]--;
};Euler(Euler, 1);
cout << "YES\n" << st.size() - 1 << '\n';
reverse(st.begin(), st.end());
for(int i = 0 ; i < (ll)st.size(); i++)
cout << st[i] << " \n"[i == st.size() - 1];
4.二分图匹配的匈牙利算法
int n, m, e, ans = 0;
std::vector<int> dfn(n + 1, 0), match(m + 1, 0);
cin >> n >> m >> e;
for(int i = 1; i <= e; i++) {
int u, v;
cin >> u >> v;
edge[u].pb(v);
}
auto dfs = [&](auto self, int u, const int tag)->bool {
if(dfn[u] == tag) return false;
dfn[u] = tag;
for(auto v : edge[u]) if(!match[v] || self(self, match[v], tag)) {
match[v] = u;
return true;
} return false;
};
for(int i = 1; i <= n; i++) ans += dfs(dfs, i, i);
cout << ans;
5.权值线段树动态开点
namespace VST {
using ll = long long;
struct vst {int v, ls, rs; ll s;};
int tot = 0;//value-SegmentTree, s = sum
void push_up(std::vector<vst> &tree, int p) {
tree[p].v = tree[tree[p].ls].v + tree[tree[p].rs].v;
}
void change(std::vector<vst> &tree, int lp, int &p, int l, int r, int q, int v) {
if(!p) p = ++tot;// build nodes dynamically
if(l == r) {
tree[p].v += v;
return;
}
int mid = l + r >> 1;
if(q <= mid) {
tree[p].rs = tree[lp].rs;
tree[p].ls = ++tot;
tree[tree[p].ls] = tree[tree[lp].ls];
change(tree, tree[lp].ls, tree[p].ls, l, mid, q, v);
}
else {
tree[p].ls = tree[lp].ls;
tree[p].rs = ++tot;
tree[tree[p].rs] = tree[tree[lp].rs];
change(tree, tree[lp].rs, tree[p].rs, mid + 1, r, q, v);
}
push_up(tree, p);
}
void update(std::vector<vst> &tree, int &p, int l, int r, int q, int v) {
if(!p) p = ++tot;// build nodes dynamically
tree[p].v += v;
tree[p].s += v * q;
if(l == r) return;
int mid = l + r >> 1;
if(q <= mid) change(tree, tree[p].ls, l, mid, q, v);
else change(tree, tree[p].rs, mid + 1, r, q, v);
push_up(tree, p);
}
int query_kth(std::vector<vst> &tree, int p1, int p2, int l, int r, int q) {
if(l == r) return l;
int mid = l + r >> 1, tmp = tree[tree[p2].ls].v - tree[tree[p1].ls].v;
if(q <= tmp) return query_kth(tree, tree[p1].ls, tree[p2].ls, l, mid, q);
else return query_kth(tree, tree[p1].rs, tree[p2].rs, mid + 1, r, q - tmp);
}
int query_sum(std::vector<vst> &tree, int p, int l, int r, ll sum) {
if(l == r) return (sum <= 0 ? 0 : (sum + l - 1) / l);
int mid = l + r >> 1;
if(tree[tree[p].rs].s >= sum)
return query_sum(tree, tree[p].rs, mid + 1, r, sum);
else
return query_sum(tree, tree[p].ls, l, mid, sum - tree[tree[p].rs].s) + tree[tree[p].rs].v;
}
void insert(std::vector<vst> &tree, std::vector<int> &node, std::vector<int> &rank, int &root, int n, int cnt) {
std::sort(rank.begin() + 1, rank.begin() + 1 + cnt);
cnt = std::unique(rank.begin(), rank.begin() + 1 + cnt) - rank.begin() - 1;
for(int i = 1; i <= n; i++) {
node[i] = std::lower_bound(rank.begin() + 1, rank.begin() + 1 + cnt, node[i]) - rank.begin();
change(tree, root, 1, cnt, node[i], 1);
}
}
}
6.ST表
namespace ST {
using i64 = long long;
void prepare_gcd(int n, std::vector<int> &a, std::vector<int> &Log, std::vector<vector<int>> &st) {
for(int i = 2; i <= n; i++) Log[i] = Log[i >> 1] + 1;
for(int j = 0; j <= Log[n]) st[j].resize(2 * n + 2);
st[0] = a;
for(int j = 1; j <= Log[n]; j++) for(int i = 1; i <= n; i++)
st[j][i] = __gcd(st[j - 1][i], st[j - 1][i + (1 << (j - 1))]);
}
int query_gcd(i64 l, i64 r, std::vector<int> &Log, std::vector<vector<int>> &st) {
int k = Log[r - l + 1];
return __gcd(st[k][l], st[k][r - (1 << k) + 1]);
}
void prepare_min(int n, std::vector<int> &a, std::vector<int> &Log, std::vector<vector<int>> &st) {
for(int i = 2; i <= n; i++) Log[i] = Log[i >> 1] + 1;
for(int j = 0; j <= Log[n]) st[j].resize(2 * n + 2);
st[0] = a;
for(int j = 1; j <= Log[n]; j++) for(int i = 1; i <= n; i++)
st[j][i] = min(st[j - 1][i], st[j - 1][i + (1 << (j - 1))]);
}
int query_min(i64 l, i64 r, std::vector<int> &Log, std::vector<vector<int>> &st) {
int k = Log[r - l + 1];
return min(st[k][l], st[k][r - (1 << k) + 1]);
}
}
7.数学
using i64 = long long;
using i128 = __int128;
namespace MATH {
using std::gcd;
using std::lcm;
using std::min;
using std::max;
using i64 = long long;
using d64 = long double;
using i128 = __int128;
using pii = std::pair<int, int>;
using pII = std::pair<std::vector<int>, std::vector<int>>;
using pll = std::pair<i64, i64>;
using pLL = std::pair<std::vector<i64>, std::vector<i64>>;
using fdd = std::function<double(double)>;
constexpr int MAXN = 1e8 + 10;
constexpr int maxn = 1e6 + 10;
constexpr int mod = 998244353;
constexpr int N = 2e5 + 10000;
constexpr double eps = 1e-9;
constexpr d64 EPS = 1e-18;
std::vector<int> phi, prime, ind;
i64 qpow(i64 a, i64 b, i64 p) {
i64 ans = 1ll % p;
for(; b != 0; b >>= 1) {
if(b & 1) ans = (i128)ans * a % p;
a = (i128)a * a % p;
}
return ans;
}
i64 qmul(i64 x, i64 y, i64 p) {
i64 ans = 0; x %= p, y %= p;
for(; y != 0; y >>= 1) {
if(y & 1) ans = (ans + x) % p;
x = (x + x) % p;
}
return ans;
}
i64 qmod(i64 x, i64 p) {
if(x >= p) return x - p;
else return x;
}
i64 exgcd(i64 a, i64 b, i64 &x, i64 &y) {
if(!b) return x = 1, y = 0, a;
i64 g = exgcd(b, a % b, y, x);
y = y - (a / b) * x; return g;
}
i64 congruence(i64 a, i64 b, i64 m) { // ax≡b(mod m)
i64 x, y, d = exgcd(a, m, x, y);
if(b % d) return -1;
else m = m / d;
return ((i128)x * (b / d) % m + m) % m;
}
i64 invmod(i64 a, i64 p) {
return congruence(a, 1ll, p);
}
i64 CRT(std::vector<i64> &r, std::vector<i64> &a) {
i128 n = 1, ans = 0;
int k = a.size();
for(auto x : r) n *= x;
for(int i = 0; i < k; i++) {
i128 m = n / r[i]; i64 R, y;
exgcd(m % r[i], r[i], R, y);
ans = (ans + (i128)a[i] * m % n * R % n) % n;
}
i64 res = (ans % n + n) % n;
return res;
}
i64 exCRT(std::vector<i64> &r, std::vector<i64> &a) {
i128 A = a[0]; i64 R = r[0];
for(int i = 1; i < (int)r.size(); i++) {
i64 p = a[i], q = r[i];
i64 x = congruence(R, (p - A) % q, q);
if(x == -1) return -1;
A += (i128)R * x;
R = std::lcm(R, q);
A %= R; if(A < 0) A += R;
}
return (A % R + R) % R;
}
i64 getphi(int n) { // phi(n)
i64 ans = 1;
for(int i = 2; i * i <= n; ++i) {
if(n % i != 0) continue;
ans *= i - 1, n /= i;
while(!(n % i)) ans *= i, n /= i;
}
if(n > 1) return ans * (n - 1);
else return ans;
}
i64 exEuler(i64 a, std::string b, i64 m) {
// a^b mod m = a^(b mod phim + phim) mod m (b >= phim)
i64 f = 0, phim = getphi(m), B = 0; // B = b mod m
for(auto &c : b) {
B = 10ll * B + c - '0';
if(B >= phim) f = 1, B %= phim; // f == 1 -> b >= phim
}
B += f ? phim : 0;
return qpow(a, B, m);
}
void EulerSieve(int n) {
phi.clear(), prime.clear();
std::vector<int> vis(n + 2, 0);
phi.resize(n + 2), prime.resize(n + 1);
int cnt = 0; phi[1] = 1;
for(int i = 2; i <= n + 1; i++) {
if(!vis[i]) prime[++cnt] = i, phi[i] = i - 1;
for(int j = 1; i * prime[j] <= n + 1 && j <= cnt; j++) {
vis[i * prime[j]] = true;
if(i % prime[j] == 0) {
phi[i * prime[j]] = phi[i] * prime[j];
break;
} else phi[i * prime[j]] = phi[i] * phi[prime[j]];
}
}
}
int MPR(int n, int p, int l = 1, int r = 50) { // minimum primitive root
int q = p; // EulerSieve first, p = phi[n]
std::vector<int> pri;
for(int i = 2; i * i <= q; i++) {
if(q % i == 0) pri.push_back(i);
while(q % i == 0) q /= i;
} if(q > 1) pri.push_back(q);
auto check = [&](int i) -> bool {
if(MATH::qpow(i, p, n) != 1) return 0;
for(auto j : pri)
if(MATH::qpow(i, p / j, n) == 1)
return 0;
return 1;
};
for(int i = l; i <= r; i++) // n^0.25
if(check(i)) return i;
return 0;
}
i64 BSGS(i64 a, i64 b, i64 p) { // a^x ≡ b (mod p) x = min
a %= p, b %= p;
if(b == 1) return 0ll;
i64 m = ceil(sqrt(p));
std::unordered_map<i64, i64> hash;
for(i64 j = 0; j < m; j++) {
hash[b] = j; // non-decreasing
b = (i128)b * a % p;
} // x = m * i - j, (a^m)^i ≡ ba^j (mod p)
i64 M = qpow(a, m, p), A = 1ll; // M = a^m, A = (a^m)^i
for(i64 i = 1; i <= m; i++) {
A = (i128)A * M % p;
if(hash.count(A)) {
i64 ans = i * m - hash[A];
if(ans >= 0) return ans;
}
}
return -1;
}
i64 exBSGS(i64 a, i64 b, i64 p) { // gcd(a,p)!=1
a %= p, b %= p;
if(b == 1 || p == 1) return 0;
i64 k = 0, d, A = 1ll;
while((d = gcd(a, p)) != 1) {
if(b % d) return -1;
++k, b /= d, p /= d;
A = (i128)A * (a / d) % p; // (a^k)/D
if(A == b) return k;
}
b = (i128)b * invmod(A, p) % p;
i64 ans = BSGS(a, b, p);
if(ans == -1) return -1;
else return ans + k;
}
void IndSieve(i64 g, i64 p) { // g has to be p's primitive root
i64 B = sqrt(p * sqrt(p) / log(p)); // Block size
std::unordered_map<i64, i64> hash;
i64 w = invmod(qpow(g, B, p), p);
i64 n = sqrt(p) + 1, Phi = p - 1; // p is prime
prime.clear(); prime.resize(n + 2);
ind.clear(); ind.resize(n + 2);
std::vector<i64> vis(n + 2, 0);
for(i64 i = 0ll, j = 1ll; i < B; i++) {
hash[j] = i, j = (i128)j * g % p;
}
auto bsgs = [&](i64 a) -> i64 { // BSGS
for(int i = 0; i <= p / B; i++) {
if(hash.count(a)) return i * B + hash[a];
a = (i128)a * w % p;
}
return -1;
};
ind[1] = 0, ind[0] = bsgs(p - 1);
for(int i = 2, cnt = 0; i <= n; i++) {
if(!vis[i]) prime[++cnt] = i, ind[i] = bsgs(i);
for(int j = 1; j <= cnt && i * prime[j] <= n; j++) {
i64 k = prime[j]; vis[i * k] = 1;
ind[i * k] = qmod(ind[i] + ind[k], Phi);
if(i % k == 0) break;
}
}
}
i64 Ind(i64 a, i64 p) { // Discrete Log
i64 lim = sqrt(p) + 1;
if(a <= lim) return ind[a];
i64 b = p / a, c = p % a, Phi = p - 1;
if(c < a - c) return qmod(qmod(ind[0] + Ind(c, p), Phi) - ind[b] + Phi, Phi);
else return qmod(Ind(a - c, p) - ind[b + 1] + Phi, Phi);
}
i64 conv(i64 a, i64 h, i64 p) { // convert to base h:ind_h(a)
// M = getphi(p), t = ind_g(a), k = ind_g(h)
i64 M = p - 1; // prime || p^(k-1)(p-1)
i64 t = Ind(a, p);
i64 k = Ind(h, p);
return congruence(k, t, M);
}
i64 DSM(i64 n, i64 k, int flag = 0) {
// Divisor Summatory Method
// sum(i*floor(n/i),i=1~n,k=n)=sum(f(i),i=1~n), f(i)=sum(divisors of i)
// f(x)+f(x+1)+...f(y)=DSM(y,y)-DSM(x-1,x-1)=(1~y)-(1~(x-1))
i64 l, r, t, ans = 0ll;
if(flag == 0) for(l = 1; l <= n; l = r + 1) {
t = k / l; if(!t) break;
r = min(n, k / t);
ans += t * (l + r) * (r - l + 1) / 2ll;
}
if(flag == 1) for(l = 1; l <= n; l = r + 1) { // sum(floor(k/i),i=1~n)
t = k / l; if(!t) break;
r = min(n, k / t);
ans += t * (r - l + 1);
}
/*
// sum(C*floor(n1/i)*floor(n2/i)...*floor(nk/i),i=1~min({nj},j=1~k))
for(l = 1; l <= min{n_1,n_2...n_k}; l = r + 1) {
i = 1~k, t_i = n_i / l; if(!t_i) break;
i = 1~k, r = min({n_i / t_i});
ans += prod(t_i,i=1~k) * (sum of coefficients)
}
*/
return ans;
}
double newton(fdd f, fdd df, double x0) {
// function f(x)=y
// f(x) = f(x0) + f'(x0)(x - x0) + o = 0
// x = x0 - f(x0) / f'(x0)
double x = x0; int maxIter = 1000;
for(int i = 0; i < maxIter; i++) {
double fx = f(x);
double dfx = df(x);
if(fabs(fx) < eps) break;
if(fabs(dfx) < eps) return nan("");
x = x - fx / dfx;
}
return x;
}
double fixn(double tar, int n = 2) {
d64 p = std::pow(10.0L, n);
d64 v = (d64)tar * p + ((tar > 0) ? 0.5L : -0.5L);
i64 iv = (i64)(v);
d64 res = (d64)iv / p;
return (double)res;
}
struct matrix { // 1-based index(start from 1 not 0)
static const int MOD = 1e9 + 7;
std::vector<std::vector<int>> G; int N;
matrix(int n = 0) {N = n; G.assign(n + 1, std::vector<int>(n + 1, 0));}
matrix(const matrix &other) {
N = other.N;
G = other.G;
}
inline void clear() {for(auto &row : G) fill(row.begin(), row.end(), 0);}
inline int size() const {return (int)G.size() - 1;}
friend matrix operator * (const matrix &a, const matrix &b) {
int n = a.N; matrix c(n);
for(int i = 1; i <= n; i++) for(int k = 1; k <= n; k++)
if(a.G[i][k]) for(int j = 1; j <= n; j++)
c.G[i][j] = (c.G[i][j] + 1ll * a.G[i][k] * b.G[k][j] % MOD) % MOD;
return c;
}
friend bool operator == (const matrix &a, const matrix &b) {
int n = a.N, m = b.N;
if(n != m) return false;
for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) {
if(a.G[i][j] != b.G[i][j]) return false;
}
return true;
}
friend bool operator != (const matrix &a, const matrix &b) {
return !(a == b);
}
friend matrix operator + (const matrix &a, const matrix &b) {
int n = a.N; matrix c(n);
for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++)
c.G[i][j] = (a.G[i][j] + b.G[i][j]) % MOD;
return c;
}
friend matrix operator - (const matrix &a, const matrix &b) {
int n = a.N; matrix c(n);
for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) {
c.G[i][j] = (a.G[i][j] - b.G[i][j]) % MOD;
if(c.G[i][j] < 0) c.G[i][j] += MOD;
}
return c;
}
matrix& operator = (const matrix &other) {
if(this != &other) G = other.G;
return *this;
}
friend std::istream & operator >> (std::istream &in, matrix &m) {
int n = m.N;
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) {
in >> m.G[i][j];
m.G[i][j] %= MOD;
}
}
return in;
}
friend std::ostream & operator << (std::ostream &out, const matrix &m) {
int n = m.N;
for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) {
out << m.G[i][j] << (j == n ? '\n' : ' ');
}
return out;
}
inline matrix mpow(i64 p) {
int n = N; matrix res(n);
for(int i = 1; i <= n; i++) res.G[i][i] = 1;
matrix base = *this;
while(p != 0) {
if(p & 1) res = res * base;
base = base * base;
p >>= 1;
}
return *this = res;
}
matrix inv() const {
int n = N; matrix A = *this, I(n), U(0);
for(int i = 1; i <= n; i++) I.G[i][i] = 1;
for(int i = 1; i <= n; i++) {
int pivot = i;
for(int j = i; j <= n; j++) if(A.G[j][i] != 0) {
pivot = j; break;
}
if(A.G[pivot][i] == 0) {
std::cout << "No Solution\n";
return U;
}
if(pivot != i) {
std::swap(A.G[i], A.G[pivot]);
std::swap(I.G[i], I.G[pivot]);
}
i64 inv_pivot = qpow(A.G[i][i], MOD - 2, MOD);
for(int j = 1; j <= n; j++) {
A.G[i][j] = 1LL * A.G[i][j] * inv_pivot % MOD;
I.G[i][j] = 1LL * I.G[i][j] * inv_pivot % MOD;
}
for(int r = 1; r <= n; r++) {
if(r == i || A.G[r][i] == 0) continue;
i64 factor = A.G[r][i];
for(int c = 1; c <= n; c++) {
A.G[r][c] = (A.G[r][c] - 1LL * factor * A.G[i][c]) % MOD;
if(A.G[r][c] < 0) A.G[r][c] += MOD;
I.G[r][c] = (I.G[r][c] - 1LL * factor * I.G[i][c]) % MOD;
if(I.G[r][c] < 0) I.G[r][c] += MOD;
}
}
}
return I;
}
};
std::vector<double> gauss(matrix A, std::vector<int> b) {
int n = A.N;
std::vector<std::vector<double>> M(n, std::vector<double>(n));
std::vector<double> B(n);
for(int i = 0; i < n; i++) B[i] = (double)b[i + 1];
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
M[i][j] = (double)A.G[i + 1][j + 1];
int rank = 0;
for(int i = 0; i < n; i++) {
int pivot = -1;
for(int j = rank; j < n; j++) {
if(fabs(M[j][i]) > EPS) {
pivot = j;
break;
}
}
if(pivot == -1) continue;
std::swap(M[rank], M[pivot]);
std::swap(B[rank], B[pivot]);
double div = M[rank][i];
for(int k = i; k < n; k++) M[rank][k] /= div;
B[rank] /= div;
for(int j = 0; j < n; j++) {
if(j == rank) continue;
if(fabs(M[j][i]) > EPS) {
double factor = M[j][i];
for(int k = i; k < n; k++) {
M[j][k] -= factor * M[rank][k];
}
B[j] -= factor * B[rank];
}
}
rank++;
}
for(int i = rank; i < n; i++)
if(fabs(B[i]) > EPS) return {-1}; // no answer
if(rank < n) return {0}; // inf answers
std::vector<double> x(n + 1, 1);
for(int i = 1; i <= n; i++) x[i] = B[i - 1];
return x;
}
i64 mxor(std::vector<i64> a) {
int n = a.size(), k = 0;
auto Gauss = [&]() -> void {
for(int i = 63; i >= 0; i--) {
for(int j = k; j < n; j++) {
if((a[j] >> i) & 1) {
std::swap(a[j], a[k]);
break;
}
}
if(((a[k] >> i) & 1) == 0) continue;
for(int j = 0; j < n; j++)
if(j != k && ((a[j] >> i) & 1))
a[j] ^= a[k];
++k; if(k == n) break;
}
}; Gauss(); i64 ans = 0ll;
for(int i = 0; i < k; i++) ans ^= a[i];
return ans;
}
struct LinearBasis {
static const int bit = 63;
i64 base[bit]; std::vector<i64> v;
int zero = 0, rank = 0;
LinearBasis() {memset(base, 0, sizeof(base)); v.clear();}
bool ask(i64 x) {
for(int i = bit - 1; i >= 0; i--)
if(x & (1ll << i)) x ^= base[i];
return x == 0;
}
void insert(i64 x) {
if(x == 0) {return zero = 1, void();}
for(int i = bit - 1; i >= 0; i--) {
if(!(x >> i & 1)) continue;
if(!base[i]) {
base[i] = x;
rank++;
return;
}
x ^= base[i];
}
if(x == 0) zero = 1;
}
void merge(LinearBasis &b) {
for(int i = bit - 1; i >= 0; i--)
if(b.base[i]) insert(b.base[i]);
}
i64 max_xor() {
i64 res = 0;
for(int i = bit - 1; i >= 0; i--)
if((res ^ base[i]) > res) res ^= base[i];
return res;
}
i64 min_xor() {
if(zero) return 0;
for(int i = 0; i < bit; i++)
if(base[i]) return base[i];
return 0;
}
void rebuild() {
i64 tmp[bit]; v.clear();
memcpy(tmp, base, sizeof(base));
for(int i = bit - 1; i >= 0; i--)
for(int j = i - 1; j >= 0; j--)
if(tmp[i] & (1ll << j)) tmp[i] ^= tmp[j];
for(int i = 0; i < bit; i++) if(tmp[i]) v.push_back(tmp[i]);
}
i64 kth_xor(i64 k) {
k -= zero; if(k == 0) return 0ll;
int r = v.size(); // rebuild first
i64 total = 1LL << r, res = 0ll;
if(k >= total) return -1;
for(int i = bit - 1; i >= 0; i--)
if(k & (1ll << i)) res ^= v[i];
return res;
}
};
}
8.并查集
namespace DSU {
std::vector<int> fa, r;
void init(int x) {
fa.resize(x + 1);
r.resize(x + 1);
fill(r.begin(), r.end(), 1);
iota(fa.begin(), fa.end(), 0);
}
int find(int x) {
return fa[x] == x ? x : fa[x] = find(fa[x]);
}
void unit(int x, int y) {
if(r[x] > r[y]) std::swap(x, y);
int a = find(x), b = find(y);
if(a == b) return;
r[b] += r[a];
fa[a] = b;
}
}
9.tarjan缩点
int id = 0, top = 0, cnt = 0;
std::vector<int> low(n + 1), dfn(n + 1, 0), st(n + 1), siz(n + 1, 0);
std::vector<bool> vis(n + 1, 0);
std::vector<int> deg(n + 1, 0), f(n + 1, 1e9), p(n + 1);
auto tarjan = [&](auto self, int u)->void{
dfn[u] = low[u] = ++ id;
st[++top] = u;
vis[u] = true;
for(auto v : adj[u]) {
if(!dfn[v]) self(self, v), low[u] = min(low[u], low[v]);
else if(vis[v]) low[u] = min(low[u], dfn[v]);
}
if(dfn[u] == low[u]) {
++cnt;
while(st[top + 1] != u) {
int v = st[top--];
vis[v] = false;
p[v] = cnt; siz[cnt]++;
f[cnt] = min(f[cnt], a[v]);
}
}
};
for(int i = 1; i <= n; i++) if(!dfn[i] && a[i] <= 2e4) tarjan(tarjan, i);
10.最大流
struct Network_Flow {
using ll = long long;
int cnt = 1, head[N], nxt[M << 1], to[M << 1], limit[M << 1];
void add(int u, int v, int w) {
nxt[++cnt] = head[u], head[u] = cnt, to[cnt] = v, limit[cnt] = w;
nxt[++cnt] = head[v], head[v] = cnt, to[cnt] = u, limit[cnt] = 0;
}
int T, dis[N], cur[N];
ll dfs(int u, ll res) {
if(u == T) return res;
ll flow = 0;
for(int i = cur[u]; i && res; i = nxt[i]) {
cur[u] = i;
int c = min(res, (ll)limit[i]), v = to[i];
if(dis[u] + 1 == dis[v] && c) {
int k = dfs(v, c);
flow += k, res -= k;
limit[i] -= k, limit[i ^ 1] += k;
}
}
if(!flow) dis[u] = -1;
return flow;
}
ll maxflow(int s, int t) {
T = t;
ll flow = 0;
while(1) {
std::queue<int> Q;
memcpy(cur, head, sizeof(head));
memset(dis, -1, sizeof(dis));
Q.push(s), dis[s] = 0;
while(!Q.empty()) {
int u = Q.front(); Q.pop();
for(int i = head[u]; i; i = nxt[i]) {
int v = to[i];
if(dis[v] == -1 && limit[i])
dis[v] = dis[u] + 1, Q.push(v);
}
}
if(dis[t] == -1) return flow;
flow += dfs(s, 1e18);
}
}
} g;
11.费用流(SPFA, 无优化)
struct Cost_Flow {
using PII = pair<int, int>;
int cnt = 1, head[N], nxt[M << 1], to[M << 1], flow[M << 1], dis[M << 1];
int incf[M << 1], pre[M << 1];
void add(int u, int v, int f, int d) {
nxt[++cnt] = head[u], to[cnt] = v, dis[cnt] = d, flow[cnt] = f, head[u] = cnt;
}// add two-way edge manually
int DIS[M << 1], vis[M << 1];
bool spfa(int s, int t) {
std::queue<int> Q;
memset(DIS, 0x3f, sizeof(DIS));
memset(vis, 0, sizeof(vis));
Q.push(s), DIS[s] = 0, vis[s] = 1;
incf[s] = 1 << 30;
while(!Q.empty()) {
int u = Q.front(); Q.pop();
vis[u] = 0;
for(int i = head[u]; i; i = nxt[i]) {
if(!flow[i]) continue;
int v = to[i];
if(DIS[v] > DIS[u] + dis[i]) {
DIS[v] = DIS[u] + dis[i];
incf[v] = min(incf[u], flow[i]);
pre[v] = i;
if(!vis[v]) vis[v] = 1, Q.push(v);
}
}
}
return DIS[t] < 1061109567;
}
PII MCMF(int s, int t) {
int mincost = 0, maxflow = 0;
while(spfa(s, t)) {
int x = t;
maxflow += incf[t];
mincost += DIS[t] * incf[t];
int i;
while(x != s) {
i = pre[x];
flow[i] -= incf[t];
flow[i ^ 1] += incf[t];
x = to[i ^ 1];
}
}
return {maxflow, mincost};
}
} G; // Graph
12.简单排序
namespace SORT {
using namespace std;
using i64 = long long;
void Sort(std::vector<int> &a, int l, int r) {
sort(a.begin() + l, a.begin() + 1 + r);
}
void quickSort(std::vector<int> &a, int l, int r) {
if(l >= r) return;
int i = l, j = r;
int pivot = a[l + (r - l) / 2];
while(i <= j) {
while(a[i] < pivot) i++;
while(a[j] > pivot) j--;
if(i <= j) {
swap(a[i], a[j]);
i++; j--;
}
}
if(l < j) quickSort(a, l, j);
if(i < r) quickSort(a, i, r);
}
i64 merge(std::vector<int> &a, int l, int mid, int r) {
std::vector<int> tmp(r - l + 1);
int i = l, j = mid + 1, k = 0;
i64 inv = 0;
while(i <= mid && j <= r) {
if(a[i] <= a[j]) tmp[k++] = a[i++];
else tmp[k++] = a[j++], inv += (mid - i + 1);
}
while(i <= mid) tmp[k++] = a[i++];
while(j <= r) tmp[k++] = a[j++];
for(int t = 0; t < (int)tmp.size(); t++)
a[l + t] = tmp[t];
return inv;
}
i64 mergeSort(std::vector<int> &a, int l, int r) {
if(l >= r) return 0;
int mid = l + r >> 1;
i64 inv = 0;
inv += mergeSort(a, l, mid);
inv += mergeSort(a, mid + 1, r);
inv += merge(a, l, mid, r);
return inv;
}
}
13.计算几何(二维)
namespace CG { // computational geometry
int sgn(double k) {
const double eps = 1e-6;
if(k > eps) return 1;
else if(k < -eps) return -1;
else return 0;
}
int cmp(double k1, double k2) {
return sgn(k1 - k2);
}
int inmid(double k1, double k2, double k3) {
return sgn(k1 - k3) * sgn(k2 - k3) <= 0;
}
struct point {
double x, y;
point operator + (const point &k1) const {return (point){k1.x + x, k1.y + y};}
point operator - (const point &k1) const {return (point){x - k1.x, y - k1.y};}
point operator * (double k1) const {return (point){x * k1, y * k1};}
point operator / (double k1) const {return (point){x / k1, y / k1};}
int operator == (const point &k1) const {return cmp(x, k1.x) == 0 && cmp(y, k1.y) == 0;}
point turn(double k1) {return (point){x * cos(k1) - y * sin(k1), x * sin(k1) + y * cos(k1)};}
point turn90() {return (point) {-y, x};}
bool operator < (const point k1) const {
int a = cmp(x, k1.x);
if(a == -1) return 1;
else if(a == 1) return 0;
else return cmp(y, k1.y) == -1;
}
double dis1() {return sqrt(x * x + y * y);}
double dis2() {return x * x + y * y;}
double dis(point k1) {return ((*this) - k1).dis1();}
point unit() {
int d = dis1();
if(d == 0) return (point){0, 0};
else return (point){x / d, y / d};
}
friend istream & operator >> (istream &input, point &p) {
input >> p.x >> p.y;
return input;
}
friend ostream & operator << (ostream &output, const point & p) {
output << fixed << setprecision(20) << p.x << " " << p.y;
return output;
}
double angle() {return atan2(y, x);}
point getdel() { // toHalf
if(sgn(x) == -1 || (sgn(x) == 0 && sgn(y) == -1))
return (*this) * (-1);
else return (*this);
}
bool getP() const {
return sgn(y) == 1 || (sgn(y) == 0 && sgn(x) == -1);
}
};
double cross(point k1, point k2) {
return k1.x * k2.y - k1.y * k2.x;
}
int inmid(point k1, point k2, point k3) {
return inmid(k1.x, k2.x, k3.x) && inmid(k1.y, k2.y, k3.y);
}
bool OnSegment(point k1, point k2, point q) {
return inmid(k1, k2, q) && sgn(cross(k1 - q, k2 - k1)) == 0;
// return sgn(cross(k2 - k1, q - k1)) == 0 && inmid(k1, k2, q);
}
point rotate(point a, double deg = 1.0, bool cw = false, point c = {0, 0}) {
double ang = deg / 180.0 * acos(-1);
if(cw == 1) ang = -ang; // clockwise
double COS = cos(ang), SIN = sin(ang);
double x = a.x - c.x;
double y = a.y - c.y;
double nx = x * COS - y * SIN;
double ny = x * SIN + y * COS;
return {nx + c.x, ny + c.y};// c = center
}
double dot(point k1, point k2) {
return k1.x * k2.x + k1.y * k2.y;
}
double rad(point k1, point k2) {
return atan2(cross(k1, k2), dot(k1, k2));
}
bool cmpAngle(point k1, point k2) {
return k1.getP() < k2.getP() || (k1.getP() == k2.getP() && sgn(cross(k1, k2)) > 0);
}
int side(point a, point b, point p) {
return sgn(cross(b - a, p - a));
}
point InterLine(point a1, point a2, point b1, point b2) {
double A1 = cross(b2 - b1, a1 - b1);
double A2 = cross(b2 - b1, a2 - b1);
return (a1 * A2 - a2 * A1) / (A2 - A1);
}
double peri(std::vector<point> poly) { // Polygon Perimeter
double res = 0;
int n = poly.size();
for(int i = 0; i < n; i++) {
res += poly[i].dis(poly[(i + 1) % n]);
}
return res;
}
double area(std::vector<point> poly) { // Polygon Area(with direction)
double res = 0;
int n = poly.size();
for(int i = 0; i < n; i++) {
res += cross(poly[i], poly[(i + 1) % n]);
}
return res / 2.0;
}
point projection(point k1, point k2, point q) {
point k = k2 - k1;
return k1 + k * (dot(q - k1, k) / k.dis2());
}
point reflect(point k1, point k2, point q) {
return projection(k1, k2, q) * 2.0 - q;
}
bool intersect(double l1, double r1, double l2, double r2) {
if(l1 > r1) swap(l1, r1);
if(l2 > r2) swap(l2, r2);
return cmp(r1, l2) != -1 && cmp(r2, l1) != -1;
}
bool InterSeg(point k1, point k2, point k3, point k4) {
return intersect(k1.x, k2.x, k3.x, k4.x) && intersect(k1.y, k2.y, k3.y, k4.y) &&
sgn(cross(k3 - k1, k4 - k1)) * sgn(cross(k3 - k2, k4 - k2)) <= 0 &&
sgn(cross(k1 - k3, k2 - k3)) * sgn(cross(k1 - k4, k2 - k4)) <= 0;
}
double disSP(point k1, point k2, point q) { // distance between segment and point
point k3 = projection(k1, k2, q);
if(inmid(k1, k2, k3)) return q.dis(k3);
else return min(q.dis(k1), q.dis(k2));
}
double disSS(point k1, point k2, point k3, point k4) { // distance between segments
if(InterSeg(k1, k2, k3, k4)) return 0;
else return min(min(disSP(k1, k2, k3), disSP(k1, k2, k4)),
min(disSP(k3, k4, k1), disSP(k3, k4, k2)));
}
struct circle {
point o;
double r;
friend istream & operator >> (istream &input, circle &p) {
return input >> p.o >> p.r;
}
int inside(point k) {
return cmp(r, o.dis(k));
}
};
struct line {
point p[2];
line(point k1, point k2) {
p[0] = k1, p[1] = k2;
}
point & operator [] (int k) {return p[k];}
int include(point k) {
return side(p[0], p[1], k) > 0;
}
point dir() { // direction
return p[1] - p[0];
}
line push(double eps = 1e-6) { // move outward eps(left side)
point delta = dir().turn90().unit() * eps;
return {p[0] - delta, p[1] - delta};
}
};
point InterLine(line k1, line k2) {
return InterLine(k1[0], k1[1], k2[0], k2[1]);
}
int parallel(line k1, line k2) {
return sgn(cross(k1.dir(), k2.dir())) == 0;
}
bool sameDir(line k1, line k2) {
return parallel(k1, k2) && sgn(dot(k1.dir(), k2.dir())) == 1;
}
bool operator < (line k1, line k2) {
if(sameDir(k1, k2)) return k2.include(k1[0]);
return cmpAngle(k1.dir(), k2.dir()); // Polar sorting
}
bool checkpos(line k1, line k2, line k3) { // about Half plane intersection
return k3.include(InterLine(k1, k2));
} // check ifor not the intersection of k1&k2 is on the left side of k3
std::vector<line> HalfPlane(std::vector<line> &L) {
//Find the intersection of half planes
//where the half plane is counterclockwise and the output is counterclockwise
std::sort(L.begin(), L.end());
std::deque<line> q;
int n = (int)L.size();
for(int i = 0; i < n; i++) {
if(i && sameDir(L[i], L[i - 1])) continue;
while(q.size() > 1 && !checkpos(q[q.size() - 2], q[q.size() - 1], L[i])) q.pop_back();
while(q.size() > 1 && !checkpos(q[1], q[0], L[i])) q.pop_front();
q.push_back(L[i]);
}
while(q.size() > 2 && !checkpos(q[q.size() - 2], q[q.size() - 1], q[0])) q.pop_back();
while(q.size() > 2 && !checkpos(q[1], q[0], q[q.size() - 1])) q.pop_front();
std::vector<line> ans;
for(int i = 0; i < q.size(); i++) ans.push_back(q[i]);
return ans;
}
double closepts(std::vector<point> &A, int l, int r) { // closest point-pair, return dis.
if(r - l <= 5) {
double ans = 1e18;
for(int i = l; i <= r; i++) for(int j = i + 1; j <= r; j++)
ans = min(ans, A[i].dis(A[j]));
return ans;
}
int mid = l + r >> 1;
double ans = min(closepts(A, l, mid), closepts(A, mid + 1, r));
std::vector<point> B;
for(int i = l; i <= r; i++) if(fabs(A[i].x - A[mid].x) <= ans) B.push_back(A[i]);
std::sort(B.begin(), B.end(), [](point k1, point k2) {return k1.y < k2.y;});
for(int i = 0; i < (int)B.size(); i++)
for(int j = i + 1; j < B.size() && B[j].y - B[i].y < ans; j++)
ans = min(ans, B[i].dis(B[j]));
return ans;
}
double cp(std::vector<point> &A) {
sort(A.begin(), A.end());
int n = A.size();
return closepts(A, 0, n - 1);
}
std::vector<point> getCL(circle k1, point k2, point k3) { // intersection of circle and line
point k = projection(k2, k3, k1.o);
double d = k1.r * k1.r - (k - k1.o).dis2();
if(sgn(d) == -1) return {};
point delta = (k3 - k2).unit() * sqrt(max((double)0.0, d));
return {k - delta, k + delta};
}
double area(circle k1, point k2, point k3) {
point k = k1.o;
k1.o = k1.o - k;
k2 = k2 - k;
k3 = k3 - k;
int pd1 = k1.inside(k2), pd2 = k1.inside(k3);
std::vector<point> A = getCL(k1, k2, k3);
if(pd1 >= 0) {
if(pd2 >= 0) return cross(k2, k3) / 2.0;
return k1.r * k1.r * rad(A[1], k3) / 2.0 + cross(k2, A[1]) / 2.0;
} else if(pd2 >= 0) {
return k1.r * k1.r * rad(k2, A[0]) / 2.0 + cross(A[0], k3) / 2.0;
} else {
int pd = cmp(k1.r, disSP(k2, k3, k1.o));
if(pd <= 0) return k1.r * k1.r * rad(k2, k3) / 2.0;
return cross(A[0], A[1]) / 2.0 + k1.r * k1.r * (rad(k2, A[0]) + rad(A[1], k3)) / 2.0;
}
}
circle getcircle(point k1, point k2, point k3) {
double a1 = k2.x - k1.x, b1 = k2.y - k1.y, c1 = (a1 * a1 + b1 * b1) / 2.0;
double a2 = k3.x - k1.x, b2 = k3.y - k1.y, c2 = (a2 * a2 + b2 * b2) / 2.0;
double d = a1 * b2 - a2 * b1;
point o = (point){k1.x + (c1 * b2 - c2 * b1) / d, k1.y + (a1 * c2 - a2 * c1) / d};
return (circle){o, k1.dis(o)};
}
circle getMCC(std::vector<point> A) { // Minimum circle coverage
std::random_device rd;
std::mt19937 rng(rd());
std::shuffle(A.begin(), A.end(), rng);
circle ans = (circle){A[0], 0};
for(int i = 1; i < (int)A.size(); i++) if(ans.inside(A[i]) == -1) {
ans = (circle){A[i], 0};
for(int j = 0; j < i; j++) if(ans.inside(A[j]) == -1) {
ans.o = (A[i] + A[j]) / 2;
ans.r = ans.o.dis(A[i]);
for(int k = 0; k < j; k++) if(ans.inside(A[k]) == -1)
ans = getcircle(A[i], A[j], A[k]);
}
}
return ans;
}
double getMDCC(std::vector<point> A) {
// Minimum Double Circle Coverage Problem
// Find two circles with the same radius that cover the given n points and have the smallest radius
// return that radius
int n = A.size();
double R = 1e18;
for(int i = 1; i <= 180; i++) {
for(int i = 0; i < n; i++) A[i] = rotate(A[i]);
std::sort(A.begin(), A.end(), [](point a, point b){return a.x < b.x;});
int l = 0, r = n - 1;
while(l <= r) {
int mid = l + r >> 1;
std::vector<point> r1, r2;
for(int i = 0; i <= mid; i++) r1.push_back(A[i]);
for(int i = mid + 1; i < n; i++) r2.push_back(A[i]);
double R1 = getMCC(r1).r;
double R2 = getMCC(r2).r;
if(min(R1, R2) > R) break;
if(R1 < R2) l = mid + 1;
else r = mid - 1;
R = min(R, max(R1, R2));
}
}
return R;
}
bool checkconvex(std::vector<point> A) {
int n = A.size();
A.push_back(A[0]);
A.push_back(A[1]);
for(int i = 0; i < n; i++)
if(sgn(cross(A[i + 1] - A[i], A[i + 2] - A[i])) == -1)
return 0;
return 1;
}
int contain(std::vector<point> A, point q) {
int pd = 0;
A.push_back(A[0]);
for(int i = 1; i < (int)A.size(); i++) {
point u = A[i - 1], v = A[i];
if(OnSegment(u, v, q)) return 1;
if(cmp(u.y, v.y) > 0) swap(u, v);
if(cmp(u.y, q.y) >= 0 || cmp(v.y, q.y) < 0) continue;
if(sgn(cross(u - v, q - v)) < 0) pd ^= 1;
}
return pd << 1;
}
std::vector<point> ConvexHull(std::vector<point> A, int flag = 1) { // flag=0 not-strict flag=1 strict
int n = A.size();
std::vector<point> ans(n * 2);
sort(A.begin(), A.end());
int now = -1;
for(int i = 0; i < A.size(); i++) {
while(now > 0 && sgn(cross(ans[now] - ans[now - 1], A[i] - ans[now - 1])) < flag) now--;
ans[++now] = A[i];
}
int pre = now;
for(int i = n - 2; i >= 0; i--) {
while(now > pre && sgn(cross(ans[now] - ans[now - 1], A[i] - ans[now - 1])) < flag) now--;
ans[++now] = A[i];
}
ans.resize(now + 1);
return ans;
}
double convexDiameter(std::vector<point> A) { // Rotating Calipers
int now = 0, n = A.size();
double ans = 0;
for(int i = 0; i < A.size(); i++) {
now = max(now, i);
while(true) {
double k1 = A[i].dis(A[now % n]);
double k2 = A[i].dis(A[(now + 1) % n]);
ans = max(ans, max(k1, k2));
if(k2 > k1) now++;
else break;
}
}
return ans;
}
} using namespace CG;
14.高精度
struct BigInteger {
static const int BASE = 1e8;
static const int WIDTH = 8;
vector<int> num;
bool sgn;
BigInteger(int x = 0) { *this = x; }
BigInteger(const string &s) { *this = s; }
BigInteger & operator = (int x) {
num.clear();
sgn = x >= 0;
if(!sgn) x = -x;
if(x == 0) num.push_back(0);
while(x > 0) {
num.push_back(x % BASE);
x /= BASE;
}
return *this;
}
BigInteger & operator = (const string &s) {
num.clear();
int len = s.size(), i = 0;
sgn = true;
if(s[0] == '-') sgn = false, i++;
for(int j = len - 1; j >= i; j -= WIDTH) {
int l = max(i, j - WIDTH + 1);
int x = 0;
for(int k = l; k <= j; k++)
x = x * 10 + (s[k] - '0');
num.push_back(x);
}
trim();
return *this;
}
void trim() {
while(num.size() > 1 && num.back() == 0) num.pop_back();
if(num.size() == 1 && num[0] == 0) sgn = true;
}
string toString() const {
stringstream ss;
if(!sgn) ss << '-';
ss << (num.empty() ? 0 : num.back());
for(int i = num.size() - 2; i >= 0; i--)
ss << setw(WIDTH) << setfill('0') << num[i];
return ss.str();
}
friend ostream &operator<<(ostream &out, const BigInteger &x) {
out << x.toString();
return out;
}
friend istream &operator>>(istream &in, BigInteger &x) {
string s;
in >> s;
x = s;
return in;
}
bool absLess(const BigInteger &rhs) const {
if(num.size() != rhs.num.size()) return num.size() < rhs.num.size();
for(int i = num.size() - 1; i >= 0; i--)
if(num[i] != rhs.num[i]) return num[i] < rhs.num[i];
return false;
}
bool operator<(const BigInteger &rhs) const {
if(sgn != rhs.sgn) return !sgn;
return sgn ? absLess(rhs) : rhs.absLess(*this);
}
bool operator > (const BigInteger &rhs) const { return rhs < *this; }
bool operator == (const BigInteger &rhs) const { return !(*this < rhs) && !(rhs < *this); }
bool operator != (const BigInteger &rhs) const { return !(*this == rhs); }
bool operator <= (const BigInteger &rhs) const { return !(*this > rhs); }
bool operator >= (const BigInteger &rhs) const { return !(*this < rhs); }
BigInteger operator - () const {
BigInteger res = *this;
if(!(num.size() == 1 && num[0] == 0)) res.sgn = !sgn;
return res;
}
BigInteger operator + (const BigInteger &rhs) const {
if(!sgn) return (-(*this) + rhs).operator-();
if(!rhs.sgn) return (*this - (-rhs));
BigInteger res;
res.sgn = true;
int carry = 0, n = max(num.size(), rhs.num.size());
res.num.resize(n);
for(int i = 0; i < n; i++) {
int a = i < (int)num.size() ? num[i] : 0;
int b = i < (int)rhs.num.size() ? rhs.num[i] : 0;
int sum = a + b + carry;
res.num[i] = sum % BASE;
carry = sum / BASE;
}
if(carry) res.num.push_back(carry);
return res;
}
BigInteger operator - (const BigInteger &rhs) const {
if(!rhs.sgn) return *this + (-rhs);
if(!sgn) return (-(*this) + rhs).operator-();
if(*this < rhs) return -(rhs - *this);
BigInteger res = *this;
int borrow = 0;
for(int i = 0; i < (int)rhs.num.size() || borrow; i++) {
res.num[i] -= (i < (int)rhs.num.size() ? rhs.num[i] : 0) + borrow;
if(res.num[i] < 0) res.num[i] += BASE, borrow = 1;
else borrow = 0;
}
res.trim();
return res;
}
BigInteger operator * (const BigInteger &rhs) const {
BigInteger res;
res.sgn = (sgn == rhs.sgn);
res.num.assign(num.size() + rhs.num.size(), 0);
for(size_t i = 0; i < num.size(); i++)
for(size_t j = 0; j < rhs.num.size(); j++)
res.num[i + j] += num[i] * rhs.num[j];
int carry = 0;
for(size_t i = 0; i < res.num.size(); i++) {
res.num[i] += carry;
carry = res.num[i] / BASE;
res.num[i] %= BASE;
}
res.trim();
return res;
}
BigInteger operator / (const BigInteger &rhs) const {
assert(rhs != 0);
BigInteger divident = *this, divisor = rhs;
divident.sgn = divisor.sgn = true;
BigInteger res, cur = 0;
res.num.resize(divident.num.size());
for(int i = divident.num.size() - 1; i >= 0; i--) {
cur.num.insert(cur.num.begin(), divident.num[i]);
cur.trim();
int l = 0, r = BASE - 1, ans = 0;
while(l <= r) {
int m = (l + r) / 2;
if(divisor * m <= cur) ans = m, l = m + 1;
else r = m - 1;
}
res.num[i] = ans;
cur = cur - divisor * ans;
}
res.sgn = (sgn == rhs.sgn);
res.trim();
return res;
}
BigInteger operator % (const BigInteger &rhs) const {
return *this - (*this / rhs) * rhs;
}
BigInteger operator + (const int &rhs) const {
return *this + BigInteger(rhs);
}
BigInteger operator - (const int &rhs) const {
return *this - BigInteger(rhs);
}
BigInteger operator * (const int &rhs) const {
BigInteger res;
res.sgn = (rhs >= 0 ? sgn : !sgn);
int mul = abs(rhs);
res.num.clear();
int carry = 0;
for(size_t i = 0; i < num.size(); i++) {
int cur = (int)num[i] * mul + carry;
res.num.push_back(cur % BigInteger::BASE);
carry = cur / BigInteger::BASE;
}
while(carry) {
res.num.push_back(carry % BigInteger::BASE);
carry /= BigInteger::BASE;
}
res.trim();
return res;
}
BigInteger operator/(const int &rhs) const {
assert(rhs != 0);
BigInteger res;
res.sgn = (rhs >= 0 ? sgn : !sgn);
int div = abs(rhs);
res.num.resize(num.size());
int rem = 0;
for(int i = num.size() - 1; i >= 0; i--) {
int cur = num[i] + rem * (int)BigInteger::BASE;
res.num[i] = cur / div;
rem = cur % div;
}
res.trim();
return res;
}
int operator % (const int &rhs) const {
assert(rhs != 0);
int rem = 0, div = abs((int)rhs);
for(int i = num.size() - 1; i >= 0; i--) {
rem = (rem * BigInteger::BASE + num[i]) % div;
}
if(!sgn) rem = -rem;
return (int)rem;
}
BigInteger qpow(BigInteger n, const BigInteger &mod) const {
BigInteger res = 1, base = *this;
while(n > 0) {
if(n.num[0] % 2 == 1) res = (res * base) % mod;
base = (base * base) % mod;
n = n / 2;
}
return res;
}
};
using i256 = BigInteger;
15.多项式
struct Poly {
std::vector<double> coef;
Poly(int n = 0) { coef.assign(n + 1, 0.0); }
Poly(const vector<double>& c) { coef = c; }
double operator()(double x) const {
double res = 0.0;
int n = coef.size() - 1;
for(int i = 0; i <= n; i++) res = res * x + coef[i];
return res;
}
double dvt(double x) const {
double res = 0.0;
int n = coef.size() - 1;
for(int i = 0; i < n; i++) res = res * x + (n - i) * coef[i];
return res;
}
friend istream& operator >> (istream& in, Poly& p) {
int n = p.coef.size() - 1;
for(int i = 0; i <= n; i++) in >> p.coef[i];
return in;
}
friend ostream& operator<<(ostream& out, const Poly& p) {
int n = p.coef.size() - 1;
int cnt = 0, pos = -1;
for(int i = 0; i <= n; i++) {
if(p.coef[i] == 0) cnt++;
if(p.coef[i] != 0 && pos == -1) pos = i;
}
if(cnt == n + 1) {
out << "0";
return out;
}
for(int i = 0; i < n - 1; i++) {
if(fabs(p.coef[i]) > 1 && p.coef[i] < 0)
out << p.coef[i] << "x^" << n - i;
if(fabs(p.coef[i]) > 1 && p.coef[i] > 0 && i > pos)
out << "+" << p.coef[i] << "x^" << n - i;
if(fabs(p.coef[i]) > 1 && p.coef[i] > 0 && i == pos)
out << p.coef[i] << "x^" << n - i;
if(fabs(p.coef[i]) == 1 && p.coef[i] < 0)
out << "-x^" << n - i;
if(fabs(p.coef[i]) == 1 && p.coef[i] > 0 && i > pos)
out << "+x^" << n - i;
if(fabs(p.coef[i]) == 1 && p.coef[i] > 0 && i == pos)
out << "x^" << n - i;
}
if(n >= 1) {
if(p.coef[n - 1] > 1) {
if(pos < n - 1) out << "+";
out << p.coef[n - 1] << "x";
} else if(p.coef[n - 1] < -1) {
out << p.coef[n - 1] << "x";
} else if(p.coef[n - 1] == 1) {
if(pos < n - 1) out << "+";
out << "x";
} else if(p.coef[n - 1] == -1) {
out << "-x";
}
}
if(fabs(p.coef[n]) < eps) return out;
if(p.coef[n] > 0 && pos < n) out << "+";
out << p.coef[n];
return out;
}
};
16.扫描线(tmp)
#include<bits/stdc++.h>
#define lp p<<1
#define rp p<<1|1
using namespace std;
struct Event {
int x, type, yl, yr;
bool operator<(const Event& o) const {
if(x != o.x) return x < o.x;
return type > o.type;
}
};
struct SegTree {
int n;
std::vector<int> mx, tag; // maximum coverage times of the current interval; lazy tag
SegTree(int n = 0): n(n), mx(4*n+4, 0), tag(4*n+4, 0) {}
void push(int p) {
if(!tag[p]) return;
mx[lp] += tag[p], tag[lp] += tag[p];
mx[rp] += tag[p], tag[rp] += tag[p];
tag[p] = 0;
}
void update(int p,int l,int r,int ql,int qr,int v){
if(qr < l || r < ql) return;
if(ql <= l && r <= qr) {
mx[p] += v;
tag[p] += v;
return;
}
int m = l + r >> 1; push(p);
update(lp,l,m,ql,qr,v);
update(rp,m+1,r,ql,qr,v);
mx[p] = max(mx[lp], mx[rp]);
}
void update(int l,int r,int v){ if(l<=r) update(1,0,n-1,l,r,v); }
int query_max() const { return mx[1]; }
};
int solve(const std::vector<tuple<int,int,int>>& circles, int W, int H){
std::vector<pair<int,int>> ySegs;
std::vector<Event> ev;
ySegs.reserve(circles.size()*2);
ev.reserve(circles.size()*2);
for(auto &[x, y, r] : circles) {
if(W < 2*r || H < 2*r) continue;
int xL = x + r - W;
int xR = x - r;
int yL = y + r - H;
int yR = y - r;
if(xL >= xR|| yL >= yR) continue;
ySegs.emplace_back(yL, yR);
ySegs.emplace_back(yL, yR);
ev.push_back({xL, +1, -1, -1});
ev.push_back({xR, -1, -1, -1});
}
if(ev.empty()) return 0;
std::vector<int> ys;
// ys.reserve(ySegs.size()*2);
for(auto &p : ySegs) {
ys.push_back(p.first);
ys.push_back(p.second);
}
std::sort(ys.begin(), ys.end());
ys.erase(unique(ys.begin(), ys.end(), [&](int a, int b){ return a == b; }), ys.end());
auto getid = [&](int v) {
int id = int(lower_bound(ys.begin(), ys.end(), v) - ys.begin());
if(id < 0) id = 0;
if(id >= (int)ys.size()) id = (int)ys.size()-1;
return id;
};
for(int i = 0; i < (int)ev.size(); ++i) {
int yL = ySegs[i].first, yR = ySegs[i].second;
int yl = getid(yL), yr = getid(yR);
if(yl > yr) swap(yl, yr);
ev[i].yl = yl, ev[i].yr = yr;
}
std::sort(ev.begin(), ev.end());
SegTree st((int)ys.size());
int ans = 0;
for(int i = 0; i < (int)ev.size();) {
int j = i, X = ev[i].x;
while(j < (int)ev.size() && ev[j].x == X && ev[j].type == 1)
st.update(ev[j].yl, ev[j].yr, +1), ++j;
ans = max(ans, st.query_max());
while(j < (int)ev.size() && ev[j].x == X && ev[j].type == -1)
st.update(ev[j].yl, ev[j].yr, -1), ++j;
i = j;
}
return ans;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int n; cin >> n;
int w, h;
cin >> w >> h;
std::vector<tuple<int,int,int>> circles(n);
for(int i = 0; i < n; ++i) {
int x,y,r;
cin >> x >> y >> r;
circles[i] = {x,y,r};
}
int ans1 = solve(circles, w, h);
int ans2 = solve(circles, h, w);
cout << max(ans1, ans2);
return 0;
}
线段树求区间
struct SegmentTree {
int n;
std::vector<i64> tree;
SegmentTree(int n = 0) { init(n); }
void init(int n_) {
n = n_, tree.assign(8 * n + 4, 0);
}
void build(std::vector<i64> &a, int p, int l, int r) {
if(l == r) {
tree[p] = a[l];
return;
}
int mid = (l + r) >> 1;
build(a, lson, l, mid);
build(a, rson, mid + 1, r);
tree[p] = std::gcd(tree[lson], tree[rson]);
}
void build(vector<i64> &a) {
build(a, 1, 1, n);
}
void update(int p, int l, int r, int pos, i64 val) {
if(l == r) {
tree[p] = val;
return;
}
int mid = (l + r) >> 1;
if(pos <= mid) update(lson, l, mid, pos, val);
else update(rson, mid + 1, r, pos, val);
tree[p] = std::gcd(tree[lson], tree[rson]);
}
void update(int pos, i64 val) {
update(1, 1, n, pos, val);
}
i64 query(int p, int l, int r, int ql, int qr) {
if(ql <= l && r <= qr) return tree[p];
int mid = (l + r) >> 1;
i64 res = 0;
if(ql <= mid) res = std::gcd(res, query(lson, l, mid, ql, qr));
if(qr > mid) res = std::gcd(res, query(rson, mid + 1, r, ql, qr));
return res;
}
i64 query(int l, int r) {
return query(1, 1, n, l, r);
}
i64 query() {
return query(1, n);
}
};