杂
#include <bits/stdc++.h>
#define rep(i, a, b) for(int i = (a), stOwxc = (b); i <= stOwxc; i++)
#define per(i, a, b) for(int i = (a), stOwxc = (b); i >= stOwxc; i--)
using namespace std;
using LL = long long;
using VI = vector<int>;
signed main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
return 0;
}
VScode 用户代码片段
{
"Print to console": {
"scope": "cpp",
"prefix": "tou",
"body": [
"#include <bits/stdc++.h>",
"#define rep(i, a, b) for(int i = (a), stOwxc = (b); i <= stOwxc; i++)",
"#define per(i, a, b) for(int i = (a), stOwxc = (b); i >= stOwxc; i--)",
"using namespace std;",
"using LL = long long;",
"using VI = vector<int>;",
"",
"signed main() {",
" ios::sync_with_stdio(0);",
" cin.tie(0); cout.tie(0);",
" $0",
" return 0;",
"}",
],
"description": "头文件"
},
"Print to console2": {
"scope": "cpp",
"prefix": "codeforces",
"body": [
"#include <bits/stdc++.h>",
"#define rep(i, a, b) for(int i = (a), stOwxc = (b); i <= stOwxc; i++)",
"#define per(i, a, b) for(int i = (a), stOwxc = (b); i >= stOwxc; i--)",
"using namespace std;",
"using LL = long long;",
"using VI = vector<int>;",
"",
"void solve() {",
" $0",
"}",
"",
"signed main() {",
" ios::sync_with_stdio(0);",
" cin.tie(0); cout.tie(0);",
" int T; cin >> T;",
" while(T--) solve();",
" return 0;",
"}",
],
"description": "头文件"
}
}
超级 IO
namespace IO {
#define iL (1 << 20)
char ibuf[iL], *iS = ibuf + iL, *iT = ibuf + iL;
#define gc() ((iS == iT) ? (iT = (iS = ibuf) + fread(ibuf, 1, iL, stdin), iS == iT ? EOF : *iS ++) : *iS ++)
template<class T> inline void read(T &x) {
x = 0;int f = 0;char ch = gc();
for (; !isdigit(ch); f |= ch == '-', ch = gc());
for (; isdigit(ch); x = (x << 1) + (x << 3) + (ch ^ 48), ch = gc());
x = (f == 1 ? ~ x + 1 : x);
}
template<class T, class... Args> inline void read(T &x, Args&... args) { read(x), read(args...); }
template<class T> inline void readch(T &x) { char ch = gc(); for (; !isalpha(ch); ch = gc()); x = ch; }
char Out[iL], *iter = Out;
#define flush() fwrite(Out, 1, iter - Out, stdout), iter = Out
template<class T> inline void write(T x, char ch = '\n') {
T l, c[35];
if (x < 0) *iter ++ = '-', x = ~ x + 1;
for (l = 0; !l || x; c[l] = x % 10, l++, x /= 10);
for (; l; -- l, *iter ++ = c[l] + '0');*iter ++ = ch;
flush();
}
template<class T, class... Args> inline void write(T x, Args... args) { write(x, ' '), write(args...); }
} // IO
using namespace IO;
高精度加法
using LL = long long;
using VI = vector<int>;
const LL p = 1e10;
struct LINT {
vector<LL> A;
int n;
LINT() : A(1) {}
LINT(LL x) : A(1) {
for(; x; x /= p) A.push_back(x % p);
n = (int)A.size() - 1;
}
LINT operator+(LINT B) {
LINT tmp; tmp.n = max(B.n, n);
tmp.A.resize(tmp.n + 1);
rep(i, 1, tmp.n) {
if(i <= n) tmp.A[i] += A[i];
if(i <= B.n) tmp.A[i] += B.A[i];
if(tmp.A[i] >= p && i + 1 > tmp.n) tmp.A.push_back(tmp.A[i] / p), tmp.n++;
else tmp.A[i + 1] += tmp.A[i] / p;
tmp.A[i] %= p;
}
return tmp;
}
LINT operator*(int x) {
LINT tmp; tmp.n = n; tmp.A = A;
rep(i, 1, tmp.n) tmp.A[i] *= x;
rep(i, 1, tmp.n - 1) tmp.A[i + 1] += tmp.A[i] / p, tmp.A[i] %= p;
for(; tmp.A[tmp.n] >= p; ) tmp.A.push_back(tmp.A[tmp.n] / p), tmp.A[tmp.n] %= p, tmp.n++;
return tmp;
}
void print() {
cout << A[n];
per(i, n - 1, 1) {
int c = 10;
while(c < p && A[i] * c < p) cout << 0, c *= 10;
cout << A[i];
}
cout << '\n';
}
};
__int128
输出
ostream &operator<<(ostream &os, const BI &n) {
if (n > 9) os << (n / 10);
return os << (int)(n % 10);
}
数据结构
DSU
struct DSU {
vector<int> fa;
DSU() {}
DSU(int n) {init(n); }
void init(int n) {
fa.resize(n + 1);
iota(fa.begin(), fa.end(), 0);
}
int find(int x) {
while(x != fa[x]) x = fa[x] = fa[fa[x]];
return x;
}
bool merge(int x, int y) {
x = find(x), y = find(y);
if(x == y) return false;
fa[x] = y;
return true;
}
bool same(int x, int y) {
return find(x) == find(y);
}
};
树状数组
struct BIT {
int n;
vector<LL> T;
BIT(int _n) : n(_n + 1) ,T(_n + 5) { };
int lowbit(int x) {return x & -x;}
void add(int x, int v) {
for(++x; x <= n; x += lowbit(x)) (T[x] += v);
}
LL ask(int x) {
LL res = 0; // 不赋初值见祖宗!!!!!
for(++x; x > 0; x -= lowbit(x)) (res += T[x]);
return res;
}
LL query(int l, int r) {
if(l > r) return 0;
return ask(r) - ask(l - 1);
}
void clear() {fill(T.begin(), T.end(), 0); }
};
区间修改查询树状数组
struct fenwick {
int n;
struct BIT {
int n;
vector<int> T;
BIT(int _n) : n(_n) ,T(_n + 5) { };
int lowbit(int x) {return x & -x;}
void modify(int x, int v) {
for(x; x <= n; x += lowbit(x)) T[x] += v;
}
ll query(int x) {
ll res = 0;
for(; x > 0; x -= lowbit(x)) res += T[x];
return res;
}
};
BIT T1, T2;
fenwick(int _n) : n(_n), T1(n), T2(n) { }
void modif(int x, int v) { T1.modify(x, (x - 1) * v); T2.modify(x, v); }
ll quer(int y) { return T2.query(y) * y - T1.query(y); }
void modify(int l, int r, int v) { modif(l ,v); modif(r + 1, -v); }
ll query(int l, int r) { return quer(r) - quer(l - 1); }
};
线段树
线段树模板新(区间最大值)
#define ls (x << 1)
#define rs ((x << 1) + 1)
struct SegTree {
int n;
struct Node {
ll mx, tag;
};
vector<Node> T;
SegTree(int _n) : n(_n), T((n << 2) + 1) {}
void apply(int x, int v) {
T[x].mx = v;
T[x].tag = v;
}
void pushdown(int x) {
if(!T[x].tag) return ;
apply(ls, T[x].tag);
apply(rs, T[x].tag);
T[x].tag = 0;
}
void update(int L, int R, ll v, int x = 1, int l = 1, int r = -1) {
if(r == -1) r = n;
if(L <= l && r <= R) {
T[x].mx = v;
T[x].tag = v;
return ;
}
int mid = l + r >> 1;
pushdown(x);
if(L <= mid) update(L, R, v, ls, l, mid);
if(R > mid) update(L, R, v, rs, mid + 1, r);
T[x].mx = max(T[ls].mx, T[rs].mx);
}
ll query(int L, int R, int x = 1, int l = 1, int r = -1) {
if(r == -1) r = n;
if(L <= l && r <= R)
return T[x].mx;
ll res = -1e18;
int mid = l + r >> 1;
pushdown(x);
if(L <= mid) res = max(res, query(L, R, ls, l, mid));
if(R > mid) res = max(res, query(L, R, rs, mid + 1, r));
return res;
}
};
#undef ls
#undef rs
区间求和线段树
#define ls (x << 1)
#define rs ((x << 1) | 1)
struct SegTree {
struct Node {
ll val, tag;
};
vector<Node> T;
int n;
SegTree() { }
SegTree(int _n) : n(_n), T((_n << 2) +5) {}
void pushdown(int x, int l, int r) {
auto &t = T[x];
if(t.tag == 0) return ;
int mid = (l + r) / 2;
(T[ls].tag += T[x].tag);
(T[rs].tag += T[x].tag);
(T[ls].val += 1ll * (mid - l + 1) * T[x].tag) ;
(T[rs].val += 1ll * (r - (mid + 1) + 1) * T[x].tag ) ;
t.tag = 0;
}
void modify(int L, int R, int v, int x = 1, int l = 1, int r = -1) {
if(r == -1) r = n;
auto &t = T[x];
assert(x <= n << 2);
if(L <= l && r <= R) {
(t.tag += v) ;
(t.val += 1ll * (r - l + 1) * v ) ;
return ;
}
pushdown(x, l, r);
int mid = (l + r) / 2;
if(L <= mid) modify(L, R, v, ls, l, mid);
if(R > mid) modify(L, R, v, rs, mid + 1, r);
(T[x].val = T[ls].val + T[rs].val) ;
}
ll query(int L, int R, int x = 1, int l = 1, int r = -1) {
if(r == -1) r = n;
auto &t = T[x];
if(L <= l && r <= R) {
return t.val;
}
pushdown(x, l, r);
int mid = (l + r) / 2;
ll res = 0;
if(L <= mid) res += query(L, R, ls, l, mid);
if(R > mid) res += query(L, R, rs, mid + 1, r);
return res;
}
};
SegTree T;
#undef ls
#undef rs
历史最值线段树
#include <bits/stdc++.h>
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define per(i ,a ,b) for(int i = (a); i >= (b); i--)
using namespace std;
const int N = 5e5 + 5;
typedef long long ll;
int n, m;
int a[N];
struct tree{
ll sum;
int l, r, maxa, cnt, se, maxb;
int add1, add2, add3, add4;
}t[N << 4];
#define ls x << 1
#define rs x << 1 | 1
void pushup(int x) {
t[x].sum = t[ls].sum + t[rs].sum;
t[x].maxa = max(t[ls].maxa, t[rs].maxa);
t[x].maxb = max(t[ls].maxb, t[rs].maxb);
if(t[ls].maxa == t[rs].maxa) {
t[x].cnt = t[ls].cnt + t[rs].cnt;
t[x].se = max(t[ls].se, t[rs].se);
}
if(t[ls].maxa > t[rs].maxa) {
t[x].cnt = t[ls].cnt;
t[x].se = max(t[ls].se, t[rs].maxa);
}
if(t[ls].maxa < t[rs].maxa) {
t[x].cnt = t[rs].cnt;
t[x].se = max(t[ls].maxa, t[rs].se);
}
}
void apply(int x, int tag1, int tag2, int tag3, int tag4) {
t[x].sum += 1ll * tag1 * t[x].cnt + 1ll * tag2 * (t[x].r - t[x].l + 1 - t[x].cnt);
t[x].maxb = max(t[x].maxb, t[x].maxa + tag3); //在给maxb赋值的时候,将 = 写成 +=,表现:区间历史最大值莫名其妙很大。
t[x].maxa += tag1;
if(t[x].se != -2e9) t[x].se += tag2;
t[x].add3 = max(t[x].add3, t[x].add1 + tag3);
t[x].add4 = max(t[x].add4, t[x].add2 + tag4);
t[x].add1 += tag1; t[x].add2 += tag2;
}
void pushdown(int x) {
int mxn = max(t[ls].maxa, t[rs].maxa);
if(t[ls].maxa == mxn)
apply(ls, t[x].add1, t[x].add2, t[x].add3, t[x].add4);
else apply(ls, t[x].add2, t[x].add2, t[x].add4, t[x].add4); //else 的赋值错误,若不是最大值则应该赋非最大值的懒标记,表现:极少情况下(有可能是数据范围太小了)会偶尔冒出来一个错误的求和操作。
if(t[rs].maxa == mxn)
apply(rs, t[x].add1, t[x].add2, t[x].add3, t[x].add4);
else apply(rs, t[x].add2, t[x].add2, t[x].add4, t[x].add4); // else 的赋值错误,若不是最大值则应该赋非最大值的懒标记,表现:极少情况下(有可能是数据范围太小了)会偶尔冒出来一个错误的求和操作。
t[x].add1 = t[x].add2 = t[x].add3 = t[x].add4 = 0;
}
void bulid(int x, int l, int r) {
t[x].l = l; t[x].r = r;
t[x].add1 = t[x].add2 = t[x].add3 = t[x].add4 = 0;
if(l == r) {
t[x].maxa = t[x].maxb = t[x].sum = a[l];
t[x].se = -2e9; t[x].cnt = 1;
return ;
}
int mid = (l + r) >> 1;
bulid(ls, l, mid);
bulid(rs, mid + 1, r);
pushup(x);
}
void modify_add(int x, int l, int r, int v) {
if(t[x].r < l || t[x].l > r) return ;
if(l <= t[x].l && t[x].r <= r) {
apply(x, v, v, v, v);
return ;
}
pushdown(x);
modify_add(ls, l, r, v); modify_add(rs, l, r, v);
pushup(x);
}
void modify_min(int x, int l, int r, int v) {
if(t[x].r < l || t[x].l > r || v >= t[x].maxa) return ; //退出条件少写了,表现:把最小值改大了。
if(l <= t[x].l && t[x].r <= r && t[x].se < v) { //条件少写了,表现:把最小值改大了。
int tmp = t[x].maxa - v;
// t[x].sum -= 1ll * t[x].cnt * tmp;
// t[x].maxa = v; t[x].add1 -= tmp;
apply(x, -tmp, 0, -tmp, 0);
// apply(x, v - t[x].maxa, 0, v - t[x].maxa, 0);
return ;
}
pushdown(x);
modify_min(ls, l, r, v); modify_min(rs, l, r, v);
pushup(x);
}
ll query_sum(int x, int l, int r) {
if(t[x].r < l || t[x].l > r) return 0;
if(l <= t[x].l && t[x].r <= r)
return t[x].sum;
pushdown(x);
return query_sum(ls, l, r) + query_sum(rs, l, r);
}
int query_maxa(int x, int l, int r) {
if(t[x].r < l || t[x].l > r) return -2e9; //不小心 return 0,而不是返回-inf,表现:最大值输出0
if(l <= t[x].l && t[x].r <= r)
return t[x].maxa;
pushdown(x);
return max(query_maxa(ls, l, r), query_maxa(rs, l, r));
}
int query_maxb(int x, int l, int r) {
if(t[x].r < l || t[x].l > r) return -2e9; //不小心 return 0,而不是返回-inf,表现:最大值输出0
if(l <= t[x].l && t[x].r <= r)
return t[x].maxb;
pushdown(x);
return max(query_maxb(ls, l, r),query_maxb(rs, l, r));
}
#undef ls
#undef rs
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n >> m;
rep(i, 1, n) cin >> a[i];
bulid(1, 1, n);
while(m--) {
int op, l, r, v;
cin >> op >> l >> r;
if(op == 1) {
cin >> v;
modify_add(1, l, r, v);
}
if(op == 2) {
cin >> v;
modify_min(1, l, r, v);
}
if(op == 3) cout << query_sum(1, l, r) << 'n';
if(op == 4) cout << query_maxa(1, l, r) << 'n';
if(op == 5) cout << query_maxb(1, l, r) << 'n';
}
return 0;
}
// P6242 【模板】线段树 3(区间最值操作、区间历史最值)
线段树合并
struct SegTree {
static constexpr int N = 5000005 + 5;
int sum[N], res[N], ls[N], rs[N];
int n, cnt = 0;
SegTree(int _n) {n = _n;}
void update(int x) {
if(sum[ls[x]] < sum[rs[x]]) {
res[x] = res[rs[x]];
sum[x] = sum[rs[x]];
}
else {
res[x] = res[ls[x]];
sum[x] = sum[ls[x]];
}
}
int merge(int a, int b, int l = 1, int r = -1) {
if (r == -1) r = n;
if(!a || !b) return max(a, b);
if(l == r) {
sum[a] += sum[b];
return a;
}
int mid = l + r >> 1;
ls[a] = merge(ls[a], ls[b], l, mid);
rs[a] = merge(rs[a], rs[b], mid + 1, r);
update(a);
return a;
}
int modify(int it, int val, int x, int l = 1, int r = -1) {
if(r == -1) r = n;
if(!x) x = ++cnt;
if(l == r) {
sum[x] += val; res[x] = it;
return x;
}
int mid = l + r >> 1;
if(it <= mid) ls[x] = modify(it, val, ls[x], l, mid);
else rs[x] = modify(it, val, rs[x], mid + 1, r);
update(x);
return x;
}
}T(1e5);
树链剖分
// P4211
#include <bits/stdc++.h>
#define rep(i, a, b) for(int i = (a), stOwxc = (b); i <= stOwxc; i++)
#define per(i, a, b) for(int i = (a), stOwxc = (b); i >= stOwxc; i--)
using namespace std;
typedef long long ll;
using VI = vector<int>;
const int mod = 201314;
#define ls (x << 1)
#define rs ((x << 1) | 1)
struct SegTree {
struct Node {
ll val, tag;
};
vector<Node> T;
int n;
SegTree() { }
SegTree(int _n) : n(_n), T((_n << 2) +5) {}
void pushdown(int x, int l, int r) {
auto &t = T[x];
if(t.tag == 0) return ;
int mid = (l + r) / 2;
(T[ls].tag += T[x].tag);
(T[rs].tag += T[x].tag);
(T[ls].val += 1ll * (mid - l + 1) * T[x].tag) ;
(T[rs].val += 1ll * (r - (mid + 1) + 1) * T[x].tag ) ;
t.tag = 0;
}
void modify(int L, int R, int v, int x = 1, int l = 1, int r = -1) {
if(r == -1) r = n;
auto &t = T[x];
assert(x <= n << 2);
if(L <= l && r <= R) {
(t.tag += v) ;
(t.val += 1ll * (r - l + 1) * v ) ;
return ;
}
pushdown(x, l, r);
int mid = (l + r) / 2;
if(L <= mid) modify(L, R, v, ls, l, mid);
if(R > mid) modify(L, R, v, rs, mid + 1, r);
(T[x].val = T[ls].val + T[rs].val) ;
}
ll query(int L, int R, int x = 1, int l = 1, int r = -1) {
if(r == -1) r = n;
auto &t = T[x];
if(L <= l && r <= R) {
return t.val;
}
pushdown(x, l, r);
int mid = (l + r) / 2;
ll res = 0;
if(L <= mid) res += query(L, R, ls, l, mid);
if(R > mid) res += query(L, R, rs, mid + 1, r);
return res;
}
};
SegTree T;
#undef ls
#undef rs
const int N = 1e5 + 5;
int si[N], dep[N], fa[N], top[N], hs[N], re[N], dfn[N];
vector<int> G[N];
void dfs1(int x, int f) {
si[x] = 1, dep[x] = dep[f] + 1; fa[x] = f;
for(auto to : G[x]) if(to != f) {
dfs1(to, x);
si[x] += si[to];
if(si[hs[x]] < si[to]) hs[x] = to;
}
}
void dfs2(int x, int tp) {
top[x] = tp;
re[x] = ++dfn[0];
if(hs[x]) dfs2(hs[x], tp);
for(auto to : G[x]) if(to != fa[x] && to != hs[x]) {
dfs2(to, to);
}
}
int n;
void mdf(int x, int y, int v) {
if(y == 0) return ;
while(top[x] != top[y]) {
if(dep[top[x]] < dep[top[y]]) swap(x, y);
T.modify(re[top[x]], re[x], v);
// T.modify(1, n, v);
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
T.modify(re[x], re[y], v);
// T.modify(1, n, v);
}
ll qry(int x, int y) {
int res = 0;
while(top[x] != top[y]) {
if(dep[top[x]] < dep[top[y]]) swap(x, y);
res += T.query(re[top[x]], re[x]);
// res += T.query(1, n);
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
res += T.query(re[x], re[y]);
return res % mod;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int m; cin >> n >> m;
T = SegTree(n);
for(int i = 2, x; i <= n; i++) cin >> x, x++, G[x].emplace_back(i), G[i].emplace_back(x);
struct Node {
int id, it, z, tag;
};
vector<Node> Q(1);
for(int i = 1, l, r, z; i <= m; i++)
cin >> l >> r >> z, l, r++, z++, Q.push_back({i, l, z, 0}), Q.push_back({i, r, z, 1});
sort(Q.begin() + 1, Q.end(), [](const Node &x, const Node &y) {
return x.it < y.it;
});
dfs1(1, 0);
dfs2(1, 0);
vector<array<int, 2>> ans(m + 1);
int nw = 0;
rep(i, 1, 2 * m) {
while(nw < Q[i].it) mdf(1, ++nw, 1);
ans[Q[i].id][Q[i].tag] = qry(1, Q[i].z);
}
rep(i, 1, m) {
// cout << ans[i][1] << " " << ans[i][0] << 'n';
cout << (ans[i][1] - ans[i][0] + mod) % mod << 'n';
}
return 0;
}
主席树
//主席树
#include <bits/stdc++.h>
#define rep(i, a, b) for(int i = (a), stOwxc = (b); i <= stOwxc; i++)
#define per(i, a, b) for(int i = (a), stOwxc = (b); i >= stOwxc; i--)
using namespace std;
typedef long long ll;
//#define int long long
struct SegTree {
int n, idx = 0;
struct Node {
int ls, rs, sum;
};
vector<Node> T;
SegTree (int _n) : n(_n), T((_n * 100) + 5) { } // 不要忘记乘以 100,不能够再小了。
int modify(int it, int ls, int l = 1, int r = -1) {
if(r == -1) r = n;
int nw = ++idx, mid = l + r >> 1;
T[nw] = T[ls]; T[nw].sum++;
if(l < r) {
if(it <= mid) T[nw].ls = modify(it, T[ls].ls, l, mid);
else T[nw].rs = modify(it, T[ls].rs, mid + 1, r);
}
return nw;
}
int query(int L, int R, int k, int l = 1, int r = -1) {
if(r == -1) r = n;
int mid = l + r >> 1;
int su = T[T[R].ls].sum - T[T[L].ls].sum;
if(l >= r) return l;
if(su >= k) return query(T[L].ls, T[R].ls, k, l, mid);
else return query(T[L].rs, T[R].rs, k - su, mid + 1, r);
}
};
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n, q; cin >> n >> q;
vector<int> A(n + 10), rt(n + 10);
rep(i, 1, n) cin >> A[i];
auto B = A;
sort(B.begin() + 1, B.begin() + 1 + n);
int nb = unique(B.begin() + 1, B.begin() + 1 + n) - B.begin() - 1;
SegTree T(nb);
rep(i, 1, n) {
int t = lower_bound(B.begin() + 1, B.begin() + 1 + nb, A[i]) - B.begin(); // 二分的时候要在 B 的范围内枚举
rt[i] = T.modify(t, rt[i - 1]);
}
for(int x, y ,z; q && cin >> x >> y >> z; q--) {
int t = T.query(rt[x - 1], rt[y], z);
cout << B[t] << 'n';
}
return 0;
}
图论
最小生成树
array<int, 3> E[M];
int vis[M];
ll mns = 0;
namespace kruskal {
vector<int> fa;
int find(int x) {return x == fa[x] ? x : fa[x] = find(fa[x]);}
bool merge(int x, int y) {
x = find(x), y = find(y);
if(x == y) return false;
fa[x] = y;
return true;
}
void work() {
sort(E + 1, E + 1 + m);
fa.resize(n + 1);
iota(fa.begin(), fa.end(0), 0);
int cnt = 1;
rep(i, 1, m) {
int x = E[i][1], y = E[i][2];
if(merge(x, y)) mns += E[i][0], cnt++, G[x].push_back({y, E[i][0]}), G[y].push_back({x, E[i][0]});
if(cnt == 0) break;
}
}
}
LCA
树链剖分
vector<int> G[maxn];
int si[maxn], top[maxn], hson[maxn], fa[maxn], dep[maxn];
void dfs1(int x, int f) {
si[x] = 1; dep[x] = dep[f] + 1; fa[x] = f;
for(auto to : G[x]) {
if(to == f) continue;
dfs1(to, x);
si[x] += si[to];
if(si[to] > si[hson[x]]) hson[x] = to;
}
}
void dfs2(int x, int tp) {
top[x] = tp;
if(!hson[x]) return ;
dfs2(hson[x], tp);
for(auto to : G[x]) {
if(to == fa[x] || to == hson[x]) continue;
dfs2(to, to);
}
}
int lca(int x, int y) {
while(top[x] != top[y]) {
if(dep[top[x]] < dep[top[y]]) swap(x, y);
x = fa[top[x]];
}
return (dep[x] < dep[y] ? x : y);
}
倍增
const int maxn = 500000 + 5;
const int maxk = 21; // log2(maxn) + 1
int fa[maxk][maxn];
int depth[maxn];
vector<int> vec[maxn];
void dfs(int x, int f)
{
fa[0][x] = f;
depth[x] = depth[f] + 1;
for (int i = 1; i < maxk; i++)
{
fa[i][x] = fa[i - 1][fa[i - 1][x]];
}
for (auto to : vec[x])
{
if (to == f)
continue;
dfs(to, x);
}
}
int LCA(int x, int y)
{
if (depth[x] < depth[y])
swap(x, y);
for (int i = maxk - 1; i >= 0; i--)
{
if (depth[fa[i][x]] >= depth[y])
x = fa[i][x];
}
if (x == y)
return x;
for (int i = maxk - 1; i >= 0; i--)
{
if (fa[i][x] != fa[i][y])
{
x = fa[i][x];
y = fa[i][y];
}
}
return fa[0][x];
}
dfs 序
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
const int maxn = 500000 + 5;
int n, m, s;
vector<int> G[maxn];
int dfn[maxn], mi[20][maxn];
int get(int x, int y) {
return dfn[x] < dfn[y] ? x : y;
}
void dfs(int x, int f) {
dfn[x] = ++dfn[0]; mi[0][dfn[x]] = f;
for(auto to : G[x]) if(to != f) dfs(to, x);
}
int lca(int x, int y) {
if(x == y) return x;
if((x = dfn[x]) > (y = dfn[y])) swap(x, y);
int d = log2(y - x++);
return get(mi[d][x], mi[d][y - (1 << d) + 1]);
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n >> m >> s;
for(int i = 1, u, v; i < n; i++) {
cin >> u >> v;
G[u].push_back(v); G[v].push_back(u);
}
dfs(s, 0);
for(int i = 1; i <= log2(n); i++) for(int j = 1; j + (1 << i) - 1 <= n; j++)
mi[i][j] = get(mi[i - 1][j], mi[i - 1][j + (1 << i - 1)]);
while(m--) {
int x, y;
cin >> x >> y;
cout << lca(x, y) << "n";
}
return 0;
}
最短路
Floyd
#include <bits/stdc++.h>
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define per(i, a, b) for(int i = (a); i >= (b); i--)
using namespace std;
typedef long long ll;
const int N = 500 + 5;
#define int long long
ll a[N][N];
int n, m, q;
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n >> m >> q;
rep(i, 1, n) rep(j, 1, n) a[i][j] = LLONG_MAX;
for(int i = 1, u, v, w; i <= m; i++) {
cin >> u >> v >> w;
a[u][v] = a[v][u] = min(a[u][v], w); //重边处理
}
rep(i, 1, n) a[i][i] = 0; //自己到自己
rep(k, 1, n) rep(i, 1, n) rep(j ,1 ,n)
if(a[i][k] != LLONG_MAX && a[k][j] != LLONG_MAX && i != k && j != k) //ik, jk 不同
a[i][j] = min(a[i][j], a[i][k] + a[k][j]);
for(int i = 1, u, v; i <= q; i++) {
cin >> u >> v;
cout << (a[u][v] == LLONG_MAX ? -1 : a[u][v]) << 'n';
}
return 0;
}
Dijkstra
struct Dijkstra {
int n; vector<LL> dis;
LL& operator[] (const int x) {return dis[x]; }
Dijkstra() {}
Dijkstra(int _n) : n(_n), dis(_n + 1, INF) { }
void init(int nn) {n = nn, dis.assign(n + 1, INF); }
void work(int st) {
priority_queue<AI, vector<AI>, greater<AI>> q;
fill(dis.begin(), dis.end(), INF);
dis[st] = 0; q.push({0, st});
while(!q.empty()) {
int x = q.top()[1], w = q.top()[0]; q.pop();
if(dis[x] < w) continue;
for(auto i : G[x]) {
int to = i[0], w = i[1];
if(dis[to] > dis[x] + w) {
dis[to] = dis[x] + w;
q.push({dis[to], to});
}
}
}
}
}dj1, dj2;
网络最大流
#include <bits/stdc++.h>
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define per(i, a, b) for(int i = (a); i >= (b); i--)
using namespace std;
typedef long long ll;
const int N = 200 + 5, M = 5000 + 5;
#define int long long
int n, m, s, t;
int tot = 1, head[M], cur[M];
int dep[M];
ll ans;
struct edge {
int v, nxt;
ll val;
}e[M * 2];
void add(int u, int v, ll w) {
e[++tot].v = v;
e[tot].val = w;
e[tot].nxt = head[u];
head[u] = tot;
e[++tot].v = u;
e[tot].val = 0;
e[tot].nxt = head[v];
head[v] = tot;
}
int bfs() {
queue<int> q;
memset(dep, 0, sizeof(dep)); //数组没有清空,表现:死循环退不出去。
q.push(s);
dep[s] = 1;
cur[s] = head[s];
while(!q.empty()) {
int u = q.front();
q.pop();
for(int i = head[u]; i; i = e[i].nxt) {
int v = e[i].v;
if(e[i].val > 0 && !dep[v]) {
q.push(v);
cur[v] = head[v];
dep[v] = dep[u] + 1;
if(v == t) return 1;
}
}
}
return dep[t];
}
int dfs(int u, ll sum) {
if(u == t || !sum) return sum;
ll k, res = 0;
for(int i = cur[u]; i && sum; i = e[i].nxt) {
int v = e[i].v;
cur[u] = i; //没有加弧优化TLE
if(e[i].val > 0 && dep[v] == dep[u] + 1) {
k = dfs(v, min(sum, e[i].val));
if(k == 0) dep[v] = 0;
e[i].val -= k;
e[i^1].val += k; //val错写成v,表现:可能死循环,也可能有一些其他的问题,尚不确定。
res += k;
sum -= k;
}
}
return res;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n >> m >> s >> t;
rep(i, 1, m) {
int u, v; ll w;
cin >> u >> v >> w;
add(u, v, w);
}
while(bfs()) {
ans += dfs(s, LLONG_MAX);
}
cout << ans << 'n';
return 0;
}
SCC
struct SCC {
int n, idx, cnt;
vector<VI> G;
VI stk, dfn, low, belong;
SCC(int _n) : n(_n), G(n + 1), low(n + 1), belong(n + 1), dfn(n + 1) {
idx = cnt = 0;
}
void add(int u, int v) {G[u].push_back(v); };
int dfs(int x) {
low[x] = dfn[x] = ++idx;
stk.push_back(x);
for(auto to : G[x]) {
if(!dfn[to])
low[x] = min(low[x], dfs(to));
else if(!belong[to])
low[x] = min(low[x], low[to]);
}
if(low[x] == dfn[x]) {
cnt++;
for(int i = -1; i != x; stk.pop_back())
i = stk.back(), belong[i] = cnt;
}
return low[x];
}
};
EBCC
struct EBCC {
int n, idx;
vector<VI> G;
VI dfn, low;
set<int> ans;
EBCC(int _n) : n(_n), dfn(_n + 1), low(_n + 1), G(_n + 1) {
idx = 0;
}
void add(int u, int v) {
G[u].push_back(v), G[v].push_back(u);
}
int dfs(int x, int p) {
int ch = 0;
low[x] = dfn[x] = ++idx;
for(auto to : G[x]) {
if(!dfn[to]) {
ch++;
int t = dfs(to, x);
low[x] = min(low[x], t);
if(t >= dfn[x] && p != -1)
ans.insert(x);
}
else
low[x] = min(low[x], dfn[to]);
}
if(ch >= 2 && p == -1) ans.insert(x);
return low[x];
}
};
点分治
#include <bits/stdc++.h>
#define rep(i, a, b) for(int i = (a), stOwxc = (b); i <= stOwxc; i++)
#define per(i, a, b) for(int i = (a), stOwxc = (b); i >= stOwxc; i--)
using namespace std;
typedef long long ll;
using VI = vector<int>;
const int N = 1e4 + 5;
int n, m;
vector<array<int, 2>> G[N];
int qe[N], vis[N], mx[N], si[N], st[N], dis[N];
vector<int> A(1);
int rt = 0;
void groot(int x, int fa, int sum) {
si[x] = 1; mx[x] = 0;
for(auto i : G[x]) {
int to = i[0];
if(to == fa || vis[to]) continue;
groot(to, x, sum);
si[x] += si[to];
mx[x] = max(mx[x], si[to]);
}
mx[x] = max(mx[x], sum - si[x]);
if(mx[x] < mx[rt]) rt = x;
}
void gdis(int x, int fa, int v, int ty) {
A.emplace_back(x);
st[x] = ty; dis[x] = v;
for(auto i : G[x]) {
int to = i[0], w =i[1];
if(to == fa || vis[to]) continue;
gdis(to, x, v + w, ty);
}
}
int ok[N];
void dfs(int x) {
vis[x] = 1;
A.assign(1, 0);
A.emplace_back(x);
dis[x] = 0; st[x] = x;
for(auto i : G[x]) {
int to = i[0];
if(vis[to]) continue;
gdis(to, x, i[1], to);
}
sort(A.begin() + 1, A.end(), [&](const int &x, const int &y) {
return dis[x] < dis[y];
});
rep(i ,1, m) {
int l = 1, r = (int) A.size() - 1;
while(l < r) {
if(dis[A[l]] + dis[A[r]] > qe[i]) r--;
else if(dis[A[l]] + dis[A[r]] < qe[i]) l++;
else if(st[A[l]] == st[A[r]]) {
if(dis[A[r]] == dis[A[r - 1]]) r--;
else l++;
}
else {
ok[i] = 1;
break;
}
}
}
for(auto i : G[x]) {
int to = i[0];
if(vis[to]) continue;
rt = 0;
groot(to, 0, si[to]);
dfs(rt);
}
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin >> n >> m;
for(int i = 1, u, v ,w; i < n; i++ )
cin >> u >> v >> w, G[u].push_back({v, w}), G[v].push_back({u, w});
rep(i, 1, m) cin >> qe[i];
mx[0] = n + 1;
groot(1, 0, n);
dfs(rt);
rep(i ,1, m) cout << (ok[i] ? "AYE" : "NAY") << '\n';
return 0;
}
树上启发式合并
#include <bits/stdc++.h>
#define rep(i, a, b) for(int i = (a), stOwxc = (b); i <= stOwxc; i++)
#define per(i, a, b) for(int i = (a), stOwxc = (b); i >= stOwxc; i--)
using namespace std;
typedef long long ll;
using VI = vector<int>;
const int N = 1e5 + 5;
vector<int> G[N];
struct BIT {
int n;
vector<int> T;
BIT(int _n) : n(_n) ,T(_n + 5) { };
int lowbit(int x) {return x & -x;}
void add(int x, int v) {
for(; x && x <= n; x += lowbit(x)) T[x] += v;
}
ll ask(int x) {
ll res = 0; // 不赋初值见祖宗!!!!!
for(; x > 0; x -= lowbit(x)) res += T[x];
return res;
}
};
BIT T(N);
int n, m;
int c[N];
int hson[N], si[N], in[N], out[N], nd[N];
void dfs1(int x, int fa) {
in[x] = ++in[0]; si[x] = 1;
nd[in[0]] = x;
for(auto to : G[x]) if(to != fa) {
dfs1(to, x);
si[x] += si[to];
if(si[hson[x]] < si[to]) hson[x] = to;
}
out[x] = in[0];
}
int ans[N], cnt[N], tot = 0;
vector<array<int, 2>> q[N];
void update(int u, int v) {
u = c[u];
T.add(cnt[u], -1);
cnt[u] += v;
T.add(cnt[u], 1);
// rep(i ,1, n) cout << cnt[i] << " \n"[i == n];
}
void getans(int x) {
// rep(i, 1, n) cout << cnt[i] << " \n"[i == n];
for(auto p : q[x]) ans[p[1]] = T.ask(1e5) - T.ask(p[0]);
}
void dfs2(int x, int fa, bool tag) {
for(auto to : G[x]) if(to != fa && to != hson[x])
dfs2(to, x, 0);
if(hson[x]) dfs2(hson[x], x, 1);
update(x, 1);
for(auto to : G[x]) if(to != hson[x] && to != fa)
rep(i, in[to], out[to]) update(nd[i], 1);
getans(x);
if(!tag) rep(i, in[x], out[x]) update(nd[i], -1);
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin >> n >> m;
fill(cnt, cnt + N, 1);
T.add(1, n);
rep(i ,1, n) cin >> c[i];
for(int i = 1, u, v; i < n; i++)
cin >> u >> v, G[u].emplace_back(v), G[v].emplace_back(u);
for(int u, c, i =1; i <= m; i++) {
cin >> u >> c;
q[u].push_back({c, i});
}
dfs1(1, 0);
dfs2(1, 0, 0);
rep(i ,1, m) cout << ans[i] << '\n';
return 0;
}
离线算法
莫队
#include <bits/stdc++.h>
#define rep(i, a, b) for(int i = (a), stOwxc = (b); i <= stOwxc; i++)
#define per(i, a, b) for(int i = (a), stOwxc = (b); i >= stOwxc; i--)
using namespace std;
typedef long long ll;
const int N = 50000 + 5;
inline ll gcd(ll s1, ll s2){return s2 == 0 ? s1 : gcd(s2, s1 % s2); }
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n, m; cin >> n >> m;
int L = sqrt(n);
vector<int> A(n + 1), cnt(n + 1);
rep(i, 1, n) cin >> A[i];
using AI = array<int, 3>;
vector<AI> Q(m + 1);
rep(i, 1, m) cin >> Q[i][0] >> Q[i][1], Q[i][2] = i;
sort(Q.begin() + 1, Q.end(), [&](const AI& x, const AI& y) {
if(x[0] / L != y[0] / L) return x[0] / L < y[0] / L;
return (x[0] / L) & 1 ? x[1] < y[1] : x[1] > y[1];
});
int l = 1, r = 0;
ll ans = 0;
vector<array<ll, 2>> aa(m + 1);
Q[0][1] = n + 1;
auto modify = [&](int &t, int tp) {
if(tp == 1) ans += 1ll * t;
else ans += 1ll * tp * (t - 1);
t += tp;
};
rep(i, 1, m) {
int nl = Q[i][0], nr = Q[i][1];
while(r < nr) modify(cnt[A[++r]], 1);
while(l > nl) modify(cnt[A[--l]], 1);
while(r > nr) modify(cnt[A[r--]], -1);
while(l < nl) modify(cnt[A[l++]], -1);
aa[Q[i][2]][0] = ans;
aa[Q[i][2]][1] = 1ll * (r - l + 1) * (r - l) / 2;
}
rep(i, 1, m) {
ll gd = gcd(aa[i][0], aa[i][1]);
if(aa[i][0] == 0) cout << "0/1n";
else cout << aa[i][0] / gd << '/' << aa[i][1] / gd<< 'n';
}
return 0;
}
CDQ 分治
#include <bits/stdc++.h>
#define rep(i, a, b) for(int i = (a), stOwxc = (b); i <= stOwxc; i++)
#define per(i, a, b) for(int i = (a), stOwxc = (b); i >= stOwxc; i--)
using namespace std;
typedef long long ll;
using VI = vector<int>;
struct BIT {
int n;
vector<int> T;
BIT(int _n) : n(_n) ,T(_n + 5) { };
int lowbit(int x) {return x & -x;}
void add(int x, int v) {
for(x; x <= n; x += lowbit(x)) T[x] += v;
}
ll ask(int x) {
ll res = 0; // 不赋初值见祖宗!!!!!
for(; x > 0; x -= lowbit(x)) res += T[x];
return res;
}
};
const int N = 1e5 + 5;
int n, m, k;
using AI = array<int, 5>;
vector<AI> A(1);
BIT T(2e5 + 5);
bool cmp(const AI &x, const AI &y) {
if(x[1] != y[1]) return x[1] < y[1];
return x[2] < y[2];
}
void cdq(int l, int r) {
if(l == r) return ;
int mid = l + r >> 1;
cdq(l, mid); cdq(mid + 1, r);
sort(A.begin() + l, A.begin() + mid + 1, cmp);
sort(A.begin() + mid + 1, A.begin() + r + 1, cmp);
int i = l, j = mid + 1;
for(; j <= r; j++) {
for(; i <= mid && A[i][1] <= A[j][1]; i++)
T.add(A[i][2], A[i][3]);
A[j][4] += T.ask(A[j][2]);
};
rep(k, l, i - 1) T.add(A[k][2], -A[k][3]);
return ;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin >> n >> k;
vector<AI> tmp(n + 2);
rep(i, 1, n) rep(j, 0, 2) cin >> tmp[i][j];
sort(tmp.begin() + 1, tmp.begin() + 1 + n);
for(int i = 1, t = 0; i <= n; i++) {
t++;
if(tmp[i] != tmp[i + 1]) {
A.push_back(tmp[i]);
A[A.size() - 1][3] = t;
t = 0;
}
}
int m = A.size() - 1;
// rep(i, 1, m) cout << A[i][0] << " " << A[i][1] << " " << A[i][2] << '\n';
cdq(1, m);
vector<int> ans(n + 1);
rep(i, 1, m) ans[A[i][4] + A[i][3] - 1] += A[i][3];
rep(i, 0, n - 1) cout << ans[i] << '\n';
return 0;
}
字符串
Hash
struct Hash {
int n; vector<ULL> XP, H;
void init(string & s, ULL x) {
n = s.size(); XP.resize(n + 1); H.resize(n + 1);
XP[0] = 1;
rep(i, 1, n) XP[i] = x * XP[i - 1] ;
H[n] = 0;
for(int i = n - 1; i >= 0; i--) H[i] = s[i] + x * H[i + 1];
}
ULL c_hash(int i, int j) {
return H[i] - H[j] * XP[j - i];
}
};
KMP
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 1e6 + 5;
char a[maxn], b[maxn];
int nxt[maxn];
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
// freopen("akioi.in", "r", stdin);
// freoepn("akioi.out", "w", stdout);
cin >> (a + 1) >> (b + 1);
int len1 = strlen(a + 1), len2 = strlen(b + 1 );
for(int i = 2, j = 0; i <= len2; i++) {
for(; j && b[i] != b[j + 1]; j = nxt[j]);
j += (b[i] == b[j + 1]);
nxt[i] = j;
}
for(int i = 1, j = 0; i <= len1; i++) {
for(; j && a[i] != b[j + 1]; j = nxt[j]);
j += (a[i] == b[j + 1]);
if(j == len2) {
cout << i - len2 + 1 << 'n';
j = nxt[j];
}
}
for(int i = 1; i <= len2; i++)
cout << nxt[i] << " n"[i == len2];
return 0;
}
Manacher
#include <bits/stdc++.h>
#define rep(i, a, b) for(int i = (a), stOwxc = (b); i <= stOwxc; i++)
#define per(i, a, b) for(int i = (a), stOwxc = (b); i >= stOwxc; i--)
using namespace std;
typedef long long ll;
using VI = vector<int>;
const int N = 1.1e7 * 2 + 5;
int R[N];
signed main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
string s, tmp; cin >> tmp;
s += "@|";
for(auto c : tmp) s += c, s += "|";
s += "#";
int n = s.size() - 1;
int ans = 0;
for(int i = 1, c = 0, r = 0; i < n; i++) {
int &j = R[i] = r < i ? 1 : min(R[c * 2 - i], r - i + 1);
while(s[i - j] == s[i + j]) j++;
ans = max(ans, j - 1);
if(i + j - 1 > r) r = i + j - 1, c = i;
}
cout << ans << '\n';
return 0;
}
Z function
#include <bits/stdc++.h>
#define rep(i, a, b) for(int i = (a), stOwxc = (b); i <= stOwxc; i++)
#define per(i, a, b) for(int i = (a), stOwxc = (b); i >= stOwxc; i--)
using namespace std;
typedef long long ll;
using VI = vector<int>;
const int N = 2e7 + 6;
int z[N], p[N];
signed main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
string a, b; cin >> b >> a;
int n = a.size(), m = b.size();
a = " " + a, b = " " + b;
z[1] = n;
for(int i = 2, l = 0, r = 0; i <= n; i++) {
int &j = z[i] = i > r ? 0 : min(r - i + 1, z[i - l + 1]) ;
while(a[1 + j] == a[i + j] && j < n) j++;
if(i + j - 1 > r) r = i + j - 1, l = i;
}
for(int i = 1, l = 0, r = 0; i <= m; i++) {
int &j = p[i] = i > r ? 0 : min(r - i + 1, z[i - l + 1]) ;
while(j < n && a[1 + j] == b[i + j]) j++;
if(i + j - 1 > r) r = i + j - 1, l = i;
}
ll ans = 0;
rep(i ,1, n) ans ^= 1ll * i * (z[i] + 1);
cout << ans << '\n';
ans = 0;
rep(i ,1, m) ans ^= 1ll * i * (p[i] + 1);
cout << ans << '\n';
return 0;
}
SA
#include <bits/stdc++.h>
#define rep(i, a, b) for(int i = (a), stOwxc = (b); i <= stOwxc; i++)
#define per(i, a, b) for(int i = (a), stOwxc = (b); i >= stOwxc; i--)
using namespace std;
typedef long long ll;
using VI = vector<int>;
constexpr int N = 1e6 + 5;
string s;
int sa[N], rk[N], ork[N], buc[N], id[N];
int n;
void work() {
int m = 1 << 7, p = 0;
rep(i, 1, n) buc[rk[i] = s[i]]++;
rep(i, 1, m) buc[i] += buc[i - 1];
per(i, n, 1) sa[buc[rk[i]]--] = i;
for(int w = 1 ; ; m = p, p = 0, w <<= 1) {
rep(i, n - w + 1, n) id[++p] = i;
rep(i ,1, n) if(sa[i] > w) id[++p] = sa[i] - w;
memset(buc, 0, m + 1 << 2);
memcpy(ork, rk, n + 1 << 2) ;
p = 0;
rep(i, 1, n) buc[rk[i]]++;
rep(i, 1, m) buc[i] += buc[i - 1];
per(i, n, 1) sa[buc[rk[id[i]]]--] = id[i];
rep(i ,1, n) rk[sa[i]] = ork[sa[i - 1]] == ork[sa[i]] && ork[sa[i - 1] + w] == ork[sa[i] + w] ? p : ++p;
// rep(i, 1, n) cout << sa[i] << " \n"[i == n];
if(p == n) return ;
}
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin >> s;
n = s.size(); s = " " + s;
work();
rep(i, 1, n) cout << sa[i] << " \n"[i == n];
return 0;
}
数学
矩阵乘法
struct Mat {
int n;
vector<VI> A;
vector<int>& operator [](int i) {return A[i];}
const vector<int>& operator [](int i) const { return A[i]; } //在矩阵乘法中放入这两个函数之后,便可以直接通过 `ans[1][5]` 访问数组元素,而不是 `ans.a[1][5]`。
Mat(int _n) : n(_n) {A.assign(n + 1, VI(n + 1, 0)); }
const Mat operator*(const Mat &B) const {
Mat C(n);
rep(i, 0, n) rep(j, 0, n)
rep(k, 0, n) (C[i][j] += (A[i][k] * B[k][j]) % mod) %= mod;
return C;
}
};
前缀线性基
struct Line {
vector<int> a, pos;
int n;
Line(int _n) : n(_n), a(_n + 1), pos(_n + 1) {}
void insert(int x, int it) {
per(i, n, 0)
if(x >> i & 1) {
if(!a[i] ) return a[i] = x, pos[i] = it, void();
else if(pos[i] < it) swap(pos[i], it), swap(a[i], x) ;
x ^= a[i];
}
}
int query(int it) {
int ret = 0;
per(i, n, 0) if(!(ret >> i & 1) && pos[i] >= it)
ret ^= a[i];
return ret;
}
};
快速幂
LL qpow(LL x, LL y){
LL ret= 1;
for(; y; y >>= 1) {
if(y & 1) (ret = ret * x) %= mod;
(x = x * x) %= mod;
}
return ret;
}
LL inv(int x) {return qpow(x, mod - 2); }
LL add(const LL x, const LL y) {
return (x + y + mod) % mod;
}
LL mul(const LL x, const LL y) {
return (x * y % mod + mod) % mod;
}
LL fac[N], iv[N];
void init() {
fac[0] = 1;
rep(i, 1, N - 1) fac[i] = mul(fac[i - 1], i);
iv[N - 1] = inv(fac[N - 1]);
per(i, N - 2, 0) iv[i] = mul(iv[i + 1], i + 1) ;
}
LL C(int y, int x) {
if(x < 0 || y < 0 || y - x < 0) return 0;
return mul(fac[y], mul(iv[x], iv[y - x])) ;
}