因为自己还得再写一遍,大部分模板得先鸽鸽鸽
注:算法名称上搞了对应模板的传送门
数论
1、逆元(线性递推)
#include <bits/stdc++.h>
#define maxn 3000010
#define LL long long
using namespace std;
LL q[maxn], n, p;
inline LL read(){
LL s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
int main(){
n = read(), p = read();
printf("%lld\n", q[1] = 1);
for (int i = 2; i <= n; ++i) printf("%lld\n", q[i] = (p - p / i) * q[p % i] % p);
return 0;
}
2、线性筛
#include <bits/stdc++.h>
#define maxn 10000010
using namespace std;
int n, m, prime[maxn], tot, flag[maxn];
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
int main(){
n = read(), m = read();
for (int i = 2; i <= n; ++i){
if (!flag[i]) prime[++tot] = i;
for (int j = 1; j <= tot && 1LL * i * prime[j] <= 1LL * n; ++j){
flag[i * prime[j]] = 1;
if (i % prime[j] == 0) break;
}
}
flag[1] = 1;
while (m--){
int x = read();
printf(flag[x] ? "No\n" : "Yes\n");
}
return 0;
}
3、miller_rabin素数判定
4、exgcd
#include <bits/stdc++.h>
using namespace std;
int x, y;
void exgcd(int a, int b){
if (!b){
x = 1, y = 0; return;
}
exgcd(b, a % b);
int tmp = x;
x = y, y = tmp - a / b * y;
}
int main(){
int a, b;
scanf("%d%d", &a, &b);
exgcd(a, b);
while (x < 0) x += b;
printf("%d\n", x);
return 0;
}
5、crt
6、excrt
其实这个我还不会(雾
7、高斯消元
8、线性基
#include <bits/stdc++.h>
#define maxn 110
#define LL long long
using namespace std;
LL p[maxn], x;
int n;
void insert(LL x){
for (int i = 62; i >= 0; --i){
if (!(x & (1LL << i))) continue;
if (!p[i]){
p[i] = x; break;
}
x ^= p[i];
}
}
int main(){
scanf("%d", &n);
for (int i = 1; i <= n; ++i){
scanf("%lld", &x);
insert(x);
}
LL ans = 0;
for (int i = 62; i >= 0; --i)
if ((ans ^ p[i]) > ans) ans ^= p[i];
printf("%lld\n", ans);
return 0;
}
9、FFT
input() and print(int(input())*int(input()))
/xyx
10、矩阵快速幂1
11、矩阵快速幂2
12、裴蜀定理
#include <bits/stdc++.h>
using namespace std;
int n, ans;
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
int gcd(int m, int n){ return !n ? m : gcd(n, m % n);
}
int main(){
n = read(), ans = read();
ans = abs(ans);
for (int i = 2; i <= n; ++i){
int x = read();
ans = gcd(ans, abs(x));
}
printf("%d\n", ans);
return 0;
}
计算几何
1、二维凸包
#include <bits/stdc++.h>
#define maxn 10010
using namespace std;
int n;
struct Point{
double x, y;
void read(){ scanf("%lf%lf", &x, &y); }
Point operator - (const Point &a) const{ return (Point) { x - a.x, y - a.y}; }
double operator * (const Point &a) const{ return x * a.y - y * a.x; }
}p[maxn], GP;
double cross(Point x, Point y, Point z){ return (y - x) * (z - x); }
double dis(Point a, Point b){
return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
bool cmp(Point x, Point y){
double tmp = cross(GP, x, y);
return tmp != 0 ? tmp > 0 : dis(x, GP) < dis(y, GP);
}
int main(){
scanf("%d", &n);
for (int i = 1; i <= n; ++i) p[i].read();
GP = p[1];
for (int i = 2; i <= n; ++i)
if (p[i].y < GP.y || (p[i].y == GP.y && p[i].x < GP.x)) GP = p[i];
sort(p + 1, p + 1 + n, cmp);
int top = 2;
for (int i = 3; i <= n; ++i){
while (top >= 2 && cross(p[top - 1], p[top], p[i]) <= 0) --top;
p[++top] = p[i];
}
double ans = 0;
for (int i = 1; i < top; ++i) ans += dis(p[i], p[i + 1]);
printf("%.2lf\n", ans + dis(p[1], p[top]));
return 0;
}
字符串
1、kmp
图论
1、kruskal求最小生成树
#include <bits/stdc++.h>
#define res register int
#define ll long long
#define maxn 200010
using namespace std;
struct node{
int x, y, len;
};
node edge[maxn];
int n, m, num, f[maxn];
inline int read(){
int s = 0, w = 1;
char c = getchar();
while (c < '0' || c > '9'){
if (c == '-') w = -1; c = getchar();
}
while (c >= '0' && c <= '9') s = (s << 1) + (s << 3) + (c ^ 48), c = getchar();
return s * w;
}
inline int get(int k){return f[k] == k ? k : f[k] = get(f[k]);}
inline bool cmp(node x, node y){return x.len < y.len;}
int main(){
n = read(), m = read();
for (res i = 1; i <= n; ++ i) f[i] = i;
for (res i = 1; i <= m; ++ i){
edge[i].x = read(), edge[i].y = read(), edge[i].len = read();
}
sort(edge + 1, edge + 1 + m, cmp);
int ans = 0;
for (res i = 1; i <= m; ++ i){
int s1 = get(edge[i].x), s2 = get(edge[i].y);
if (s1 != s2){
f[s1] = s2; ans += edge[i].len;
if (++num >= n - 1) break;
}
}
if (num >= n - 1) printf("%d\n", ans); else printf("orz\n");
}
2、最小瓶颈路
3、dijkstra最短路
#include <bits/stdc++.h>
#define res register int
#define ll long long
#define maxn 2 * 200010
using namespace std;
struct node {
int u, len;
bool operator < (const node &x) const {
return len > x.len;
}
};
struct Edge {
int to, next, len;
} edge[maxn];
int n, m, s, head[maxn], dis[maxn], vis[maxn], num;
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) w |= c == '-';
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
inline void add_edge(int x, int y, int z) { edge[++ num].to = y; edge[num].next = head[x]; edge[num].len = z; head[x] = num; }
int main() {
//input
n = read(), m = read(), s = read();
for (res i = 1; i <= m; ++ i) {
int x = read(), y = read(), z = read();
add_edge(x, y, z);
}
//dijkstra
memset(dis, 0x3f, sizeof(dis)); dis[s] = 0;
priority_queue <node> q;
q.push( (node) { s, 0 });
while (!q.empty()) {
node tmp = q.top(); q.pop();
int u = tmp.u, len = tmp.len;
if (vis[u]) continue;
vis[u] = 1;
for (res i = head[u]; i; i = edge[i].next) {
int v = edge[i].to;
if (dis[v] > len + edge[i].len){
dis[v] = len + edge[i].len;
q.push( (node) { v, dis[v] });
}
}
}
//output
for (res i = 1; i <= n; ++ i) printf("%d ", dis[i]);
return 0;
}
4、spfa最短路
5、缩点
#include <bits/stdc++.h>
#define maxn 100010
using namespace std;
struct Edge{
int to, next;
}edge[maxn << 1];
int num, head[maxn], Index, dfn[maxn], low[maxn], top, vis[maxn], sta[maxn];
int dp[maxn], n, m, sum[maxn], val[maxn], x[maxn], y[maxn], tot, ans, color[maxn];
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
void addedge(int x, int y){ edge[++num] = (Edge) { y, head[x] }; head[x] = num; }
void tarjan(int u){
dfn[u] = low[u] = ++Index;
vis[u] = 1, sta[++top] = u;
//赋值dfn,low
//入栈
for (int i = head[u]; i; i = edge[i].next){
int v = edge[i].to;
if (!dfn[v]) tarjan(v), low[u] = min(low[u], low[v]); else
if (vis[v]) low[u] = min(low[u], dfn[v]);
}
if (dfn[u] == low[u]){
++tot;
while (sta[top + 1] != u) color[sta[top]] = tot, vis[sta[top]] = 0, sum[tot] += val[sta[top--]];
//color表示强连通分量编号,vis表示是否在栈中,sum表示强连通分量权值和
}
}
void dfs(int u){
if (dp[u]) return;
dp[u] = sum[u];
for (int i = head[u]; i; i = edge[i].next){
int v = edge[i].to;
dfs(v);
dp[u] = max(dp[u], dp[v] + sum[u]);//这里是记忆化
}
}
int main(){
n = read(), m = read();
for (int i = 1; i <= n; ++i) val[i] = read();
for (int i = 1; i <= m; ++i){
x[i] = read(), y[i] = read();
addedge(x[i],y[i]);
}
for (int i = 1; i <= n; ++i)
if (!dfn[i]) tarjan(i);
num = 0;
memset(head, 0, sizeof(head));
for (int i = 1; i <= m; ++i)
if (color[x[i]] != color[y[i]]) addedge(color[x[i]], color[y[i]]);//重新连边,一个强连通分量缩成一个点
for (int i = 1; i <= tot; ++i)
if (!dp[i]){
dfs(i);
ans = max(ans, dp[i]);
}
printf("%d\n", ans);
return 0;
}
6、割点
#include <bits/stdc++.h>
#define maxn 100010
using namespace std;
struct Edge{
int to, next;
}edge[maxn << 1];
int num, head[maxn], Index, dfn[maxn], low[maxn], n, m, cut[maxn];
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
void addedge(int x, int y){ edge[++num] = (Edge) { y, head[x] }; head[x] = num; }
void tarjan(int u, int fa){
dfn[u] = low[u] = ++Index;
int child = 0;
for (int i = head[u]; i; i = edge[i].next){
int v = edge[i].to;
if (!dfn[v]){
tarjan(v, fa);
low[u] = min(low[u], low[v]);
if (low[v] >= dfn[u] && u != fa) cut[u] = 1;
if (u == fa) ++child;
}
low[u] = min(low[u], dfn[v]);
}
if (u == fa && child >= 2) cut[u] = 1;
}
int main(){
n = read(), m = read();
for (int i = 1; i <= m; ++i){
int x = read(), y = read();
addedge(x, y); addedge(y, x);
}
for (int i = 1; i <= n; ++i)
if (!dfn[i]) tarjan(i, i);
int ans = 0;
for (int i = 1; i <= n; ++i) ans += cut[i];
printf("%d\n", ans);
for (int i = 1; i <= n; ++i)
if (cut[i]) printf("%d ", i);
return 0;
}
7、树的直径
8、Tarjan求lca
9、倍增求lca
#include <bits/stdc++.h>
#define maxn 500010
using namespace std;
struct Edge{
int to, next;
}edge[maxn << 1];
int num, head[maxn], d[maxn], fa[maxn][25], n, m, r;
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
void addedge(int x, int y){ edge[++num] = (Edge){ y, head[x] }; head[x] = num; }
void dfs(int u, int pre){
d[u] = d[pre] + 1, fa[u][0] = pre;
for (int i = 0; fa[u][i]; ++i) fa[u][i + 1] = fa[fa[u][i]][i];
for (int i = head[u]; i; i = edge[i].next){
int v = edge[i].to;
if (v != pre) dfs(v, u);
}
}
int lca(int x, int y){
if (d[x] < d[y]) swap(x, y);
for (int i = 20; i >= 0; --i) if (d[fa[x][i]] >= d[y]) x = fa[x][i];
if (x == y) return x;
for (int i = 20; i >= 0; --i) if (fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i];
return fa[x][0];
}
int main(){
n = read(), m = read(), r = read();
for (int i = 1; i < n; ++i){
int x = read(), y = read();
addedge(x, y); addedge(y, x);
}
dfs(r, 0);
while (m--){
int x = read(), y = read();
printf("%d\n", lca(x, y));
}
return 0;
}
10、树剖求lca
#include <bits/stdc++.h>
#define maxn 500010
using namespace std;
struct Edge{
int to, next;
}edge[maxn << 1];
int num, head[maxn], size[maxn], son[maxn], d[maxn], fa[maxn], top[maxn], n, m, r;
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
void addedge(int x, int y){ edge[++num] = (Edge){ y, head[x] }; head[x] = num; }
void dfs(int u){
size[u] = 1, son[u] = -1;
for (int i = head[u]; i; i = edge[i].next){
int v = edge[i].to;
if (v != fa[u]){
d[v] = d[u] + 1, fa[v] = u;
dfs(v);
size[u] += size[v];
if (son[u] == -1 || son[u] != -1 && size[son[u]] < size[v]) son[u] = v;
}
}
}
void dfs(int u, int x){
top[u] = x;
if (son[u] == -1) return;
dfs(son[u], x);
for (int i = head[u]; i; i = edge[i].next){
int v = edge[i].to;
if (v != fa[u] && v != son[u]) dfs(v, v);
}
}
int main(){
n = read(), m = read(), r = read();
for (int i = 1; i < n; ++i){
int x = read(), y = read();
addedge(x, y); addedge(y, x);
}
dfs(r); dfs(r, r);
while (m--){
int x = read(), y = read();
while (top[x] != top[y]){
if (d[top[x]] < d[top[y]]) swap(x, y);
x = fa[top[x]];
}
printf("%d\n", d[x] < d[y] ? x : y);
}
return 0;
}
数据结构
1、树状数组1
#include <bits/stdc++.h>
#define maxn 500010
using namespace std;
int n, m, tree[maxn];
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
void update(int x, int y){ for (; x <= n; x += x & -x) tree[x] += y; }
int query(int x){ int sum = 0; for (; x; x -= x & -x) sum += tree[x]; return sum; }
int main(){
n = read(), m = read();
for (int i = 1; i <= n; ++i){ int x = read(); update(i, x); }
while (m--){
int opt = read(), x = read(), y = read();
if (opt == 1) update(x, y); else printf("%d\n", query(y) - query(x - 1));
}
return 0;
}
2、树状数组2
#include <bits/stdc++.h>
#define maxn 500010
using namespace std;
int n, m, tree[maxn];
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
void update(int x, int y){ for (; x <= n; x += x & -x) tree[x] += y; }
int query(int x){ int sum = 0; for (; x; x -= x & -x) sum += tree[x]; return sum; }
int main(){
n = read(), m = read();
for (int i = 1; i <= n; ++i){ int x = read(); update(i, x); update(i + 1, -x); }
while (m--){
int opt = read(), x = read();
if (opt == 1){
int y = read(), k = read();
update(x, k); update(y + 1, -k);
} else printf("%d\n", query(x));
}
return 0;
}
3、线段树1
#include <bits/stdc++.h>
#define maxn 100010
#define LL long long
#define ls rt << 1
#define rs rt << 1 | 1
using namespace std;
struct Seg{
LL l, r, sum, tag;
}seg[maxn << 2];
int a[maxn], n, m;
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
void pushup(int rt){ seg[rt].sum = seg[ls].sum + seg[rs].sum; }
void pushdown(int rt){
if (seg[rt].tag){
seg[ls].sum += (seg[ls].r - seg[rt].l + 1) * seg[rt].tag;
seg[rs].sum += (seg[rs].r - seg[rs].l + 1) * seg[rt].tag;
seg[ls].tag += seg[rt].tag, seg[rs].tag += seg[rt].tag;
seg[rt].tag = 0;
}
}
void build(int rt, int l, int r){
seg[rt].l = l, seg[rt].r = r;
if (l == r){ seg[rt].sum = a[l]; return; }
int mid = (l + r) >> 1;
build(ls, l, mid); build(rs, mid + 1, r);
pushup(rt);
}
void update(int rt, int l, int r, int k){
if (seg[rt].l > r || seg[rt].r < l) return;
if (seg[rt].l >= l && seg[rt].r <= r){
seg[rt].sum += (seg[rt].r - seg[rt].l + 1) * k;
seg[rt].tag += k;
return;
}
pushdown(rt);
update(ls, l, r, k); update(rs, l, r, k);
pushup(rt);
}
LL query(int rt, int l, int r){
if (seg[rt].l > r || seg[rt].r < l) return 0;
if (seg[rt].l >= l && seg[rt].r <= r) return seg[rt].sum;
pushdown(rt);
return query(ls, l, r) + query(rs, l, r);
}
int main(){
n = read(), m = read();
for (int i = 1; i <= n; ++i) a[i] = read();
build(1, 1, n);
while (m--){
int opt = read(), x = read(), y = read();
if (opt == 1){
int k = read(); update(1, x, y, k);
} else printf("%lld\n", query(1, x, y));
}
return 0;
}
4、线段树2
#include <bits/stdc++.h>
#define maxn 100010
#define LL long long
#define ls rt << 1
#define rs rt << 1 | 1
using namespace std;
struct Seg{
int l, r;
LL sum, mul, add;
}seg[maxn << 2];
int n, m, a[maxn], qy;
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
void pushup(int rt){ seg[rt].sum = (seg[ls].sum + seg[rs].sum) % qy; }
void pushdown(int rt){
seg[ls].sum = (seg[ls].sum * seg[rt].mul % qy + (seg[ls].r - seg[ls].l + 1) * seg[rt].add % qy) % qy;
seg[rs].sum = (seg[rs].sum * seg[rt].mul % qy + (seg[rs].r - seg[rs].l + 1) * seg[rt].add % qy) % qy;
seg[ls].mul = seg[ls].mul * seg[rt].mul % qy;
seg[rs].mul = seg[rs].mul * seg[rt].mul % qy;
seg[ls].add = (seg[ls].add * seg[rt].mul % qy + seg[rt].add) % qy;
seg[rs].add = (seg[rs].add * seg[rt].mul % qy + seg[rt].add) % qy;
seg[rt].mul = 1, seg[rt].add = 0;
}
void build(int rt, int l, int r){
seg[rt].l = l, seg[rt].r = r, seg[rt].add = 0, seg[rt].mul = 1;
if (l == r){ seg[rt].sum = a[l] % qy; return; }
int mid = (l + r) >> 1;
build(ls, l, mid); build(rs, mid + 1, r);
pushup(rt);
}
void mul(int rt, int l, int r, int k){
if (seg[rt].l > r || seg[rt].r < l) return;
if (seg[rt].l >= l && seg[rt].r <= r){
seg[rt].sum = seg[rt].sum * k % qy;
seg[rt].mul = seg[rt].mul * k % qy;
seg[rt].add = seg[rt].add * k % qy;
return;
}
pushdown(rt);
mul(ls, l, r, k); mul(rs, l, r, k);
pushup(rt);
}
void add(int rt, int l, int r, int k){
if (seg[rt].l > r || seg[rt].r < l) return;
if (seg[rt].l >= l && seg[rt].r <= r){
seg[rt].sum = (seg[rt].sum + (seg[rt].r - seg[rt].l + 1) * k % qy) % qy;
seg[rt].add = (seg[rt].add + k) % qy;
return;
}
pushdown(rt);
add(ls, l, r, k); add(rs, l, r, k);
pushup(rt);
}
LL query(int rt, int l, int r){
if (seg[rt].l > r || seg[rt].r < l) return 0;
if (seg[rt].l >= l && seg[rt].r <= r) return seg[rt].sum;
pushdown(rt);
return (query(ls, l, r) + query(rs, l, r)) % qy;
}
int main(){
n = read(), m = read(), qy = read();
for (int i = 1; i <= n; ++i) a[i] = read();
build(1, 1, n);
while (m--){
int opt = read(), x = read(), y = read();
if (opt == 1){ int k = read(); mul(1, x, y, k); } else
if (opt == 2){ int k = read(); add(1, x ,y, k); } else
printf("%lld\n", query(1, x, y));
}
return 0;
}
5、ST
#include <bits/stdc++.h>
#define maxn 100010
using namespace std;
int f[maxn][25], n, m, power[maxn];
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
int main(){
n = read(), m = read();
for (int i = 1; i <= n; ++i) f[i][0] = read();
power[0] = 1;
for (int i = 1; i <= 20; ++i) power[i] = power[i - 1] << 1;
for (int j = 1; j <= 20; ++j)
for (int i = 1; i + power[j - 1] <= n; ++i)
f[i][j] = max(f[i][j - 1], f[i + power[j - 1]][j - 1]);
while (m--){
int l = read(), r = read(), k = log2(r - l + 1);
printf("%d\n", max(f[l][k], f[r - power[k] + 1][k]));
}
return 0;
}
6、并查集
#include <bits/stdc++.h>
#define maxn 100010
using namespace std;
int n, m, f[maxn];
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
int get(int k){ return f[k] == k ? k : f[k] = get(f[k]);
}
int main(){
n = read(), m = read();
for (int i = 1; i <= n; ++i) f[i] = i;
while (m--){
int opt = read(), x = read(), y = read();
if (opt == 1){
int s1 = get(x), s2 = get(y);
if (s1 != s2) f[s1] = s2;
} else printf(get(x) == get(y) ? "Y\n" : "N\n");
}
return 0;
}
7、trie
8、树剖
#include <bits/stdc++.h>
#define maxn 100010
#define ls rt << 1
#define rs rt << 1 | 1
using namespace std;
struct Seg{
int l, r, tag, sum;
}seg[maxn << 2];
struct Edge{
int to, next;
}edge[maxn << 1];
int num, head[maxn], size[maxn], son[maxn], d[maxn], fa[maxn];
int id[maxn], cnt, w[maxn], wt[maxn], top[maxn];
int n, m, qy, r;
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
void addedge(int x, int y){ edge[++num] = (Edge) { y, head[x] }; head[x] = num; }
void dfs(int u){
size[u] = 1, son[u] = -1;
for (int i = head[u]; i; i = edge[i].next){
int v = edge[i].to;
if (v != fa[u]){
d[v] = d[u] + 1, fa[v] = u;
dfs(v);
size[u] += size[v];
if (son[u] == -1 || son[u] != -1 && size[son[u]] < size[v]) son[u] = v;
}
}
}
void dfs(int u, int x){
id[u] = ++cnt, wt[cnt] = w[u] % qy, top[u] = x;
if (son[u] == -1) return;
dfs(son[u], x);
for (int i = head[u]; i; i = edge[i].next){
int v = edge[i].to;
if (v != fa[u] && v != son[u]) dfs(v, v);
}
}
void pushup(int rt){ seg[rt].sum = (seg[ls].sum + seg[rs].sum) % qy; }
void pushdown(int rt){
seg[ls].sum = (seg[ls].sum + (seg[ls].r - seg[ls].l + 1) * seg[rt].tag % qy) % qy;
seg[rs].sum = (seg[rs].sum + (seg[rs].r - seg[rs].l + 1) * seg[rt].tag % qy) % qy;
seg[ls].tag = (seg[ls].tag + seg[rt].tag) % qy;
seg[rs].tag = (seg[rs].tag + seg[rt].tag) % qy;
seg[rt].tag = 0;
}
void build(int rt, int l, int r){
seg[rt].l = l, seg[rt].r = r;
if (l == r){ seg[rt].sum = wt[l]; return; }
int mid = (l + r) >> 1;
build(ls, l, mid); build(rs, mid + 1, r);
pushup(rt);
}
void update(int rt, int l, int r, int k){
if (seg[rt].l > r || seg[rt].r < l) return;
if (seg[rt].l >= l && seg[rt].r <= r){
seg[rt].sum = (seg[rt].sum + (seg[rt].r - seg[rt].l + 1) * k % qy) % qy;
seg[rt].tag = (seg[rt].tag + k) % qy;
return;
}
pushdown(rt);
update(ls, l, r, k); update(rs, l, r, k);
pushup(rt);
}
int query(int rt, int l, int r){
if (seg[rt].l > r || seg[rt].r < l) return 0;
if (seg[rt].l >= l && seg[rt].r <= r) return seg[rt].sum;
pushdown(rt);
return (query(ls, l, r) + query(rs, l, r)) % qy;
}
void updrange(int x, int y, int z){
while (top[x] != top[y]){
if (d[top[x]] < d[top[y]]) swap(x, y);
update(1, id[top[x]], id[x], z);
x = fa[top[x]];
}
if (d[x] > d[y]) swap(x, y);
update(1, id[x], id[y], z);
}
void qryrange(int x, int y){
int ans = 0;
while (top[x] != top[y]){
if (d[top[x]] < d[top[y]]) swap(x, y);
ans = (ans + query(1, id[top[x]], id[x])) % qy;
x = fa[top[x]];
}
if (d[x] > d[y]) swap(x, y);
ans = (ans + query(1, id[x], id[y])) % qy;
printf("%d\n", ans);
}
void updsize(int x, int z){ update(1, id[x], id[x] + size[x] - 1, z); }
int qrysize(int x){ printf("%d\n", query(1, id[x], id[x] + size[x] - 1)); }
int main(){
n = read(), m = read(), r = read() ,qy = read();
for (int i = 1; i <= n; ++i) w[i] = read();
for (int i = 1; i < n; ++i){
int x = read(), y = read();
addedge(x, y); addedge(y, x);
}
dfs(r); dfs(r, r);
build(1, 1, n);
while (m--){
int opt = read(), x = read();
if (opt == 1){ int y = read(), z = read(); updrange(x, y, z); } else
if (opt == 2){ int y = read(); qryrange(x, y); } else
if (opt == 3){ int z = read(); updsize(x, z); } else qrysize(x);
}
return 0;
}
9、主席树1
#include <bits/stdc++.h>
#define maxn 200010
using namespace std;
struct Chair{
int l, r, sum;
}seg[maxn << 5];
int rt[maxn], sz, n, m, a[maxn], b[maxn], p, q;
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
void build(int &rt, int l, int r){
seg[rt = ++sz].sum = 0;
if (l == r) return;
int mid = (l + r) >> 1;
build(seg[rt].l, l, mid); build(seg[rt].r, mid + 1, r);
}
int update(int o, int l, int r){
int oo = ++sz;
seg[oo] = seg[o]; ++seg[oo].sum;
if (l == r) return oo;
int mid = (l + r) >> 1;
if (mid >= p) seg[oo].l = update(seg[oo].l, l, mid); else
seg[oo].r = update(seg[oo].r, mid + 1, r);
return oo;
}
int query(int u, int v, int l, int r, int k){
int mid = (l + r) >> 1, x = seg[seg[v].l].sum - seg[seg[u].l].sum;
if (l == r) return l;
if (k <= x) return query(seg[u].l, seg[v].l, l, mid, k); else
return query(seg[u].r, seg[v].r, mid + 1, r, k - x);
}
int main(){
n = read(), m = read();
for (int i = 1; i <= n; ++i) a[i] = read(), b[i] = a[i];
sort(b + 1, b + 1 + n);
q = unique(b + 1, b + 1 + n) - b - 1;
build(rt[0], 1, q);
for (int i = 1; i <= n; ++i){
p = lower_bound(b + 1, b + 1 + q, a[i]) - b;
rt[i] = update(rt[i - 1], 1, q);
}
while (m--){
int l = read(), r = read(), k = read();
printf("%d\n", b[query(rt[l - 1], rt[r], 1, q, k)]);
}
return 0;
}
10、主席树2
#include <bits/stdc++.h>
#define maxn 1000010
using namespace std;
struct Chair{
int l, r, v;
}seg[maxn << 5];
int rt[maxn], sz, n, m, a[maxn];
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
void build(int &rt, int l, int r){
rt = ++sz;
if (l == r){ seg[rt].v = a[l]; return; }
int mid = (l + r) >> 1;
build(seg[rt].l, l, mid); build(seg[rt].r, mid + 1, r);
}
int update(int o, int l, int r, int x, int y){
int oo = ++sz;
seg[oo] = seg[o];
if (l == r){ seg[oo].v = y; return oo; }
int mid = (l + r) >> 1;
if (mid >= x) seg[oo].l = update(seg[oo].l, l, mid, x, y); else
seg[oo].r = update(seg[oo].r, mid + 1, r, x, y);
return oo;
}
int query(int rt, int l, int r, int x){
int mid = (l + r) >> 1;
if (l == r) return seg[rt].v;
if (mid >= x) return query(seg[rt].l, l, mid, x); else
return query(seg[rt].r, mid + 1, r, x);
}
int main(){
n = read(), m = read();
for (int i = 1; i <= n; ++i) a[i] = read();
build(rt[0], 1, n);
for (int i = 1; i <= m; ++i){
int x = read(), opt = read(), y = read();
if (opt == 1){
int z = read();
rt[i] = update(rt[x], 1, n, y, z);
} else{
rt[i] = rt[x];
printf("%d\n", query(rt[x], 1, n, y));
}
}
return 0;
}
11、Splay1
#include <bits/stdc++.h>
#define maxn 100010
using namespace std;
int rt, sz, f[maxn], size[maxn], recy[maxn], val[maxn], son[maxn][2];
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c= getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
void clear(int x){ f[x] = size[x] = recy[x] = val[x] = son[x][0] = son[x][1] = 0; }
int get(int x){ return son[f[x]][1] == x; }
void pushup(int x){
if (x){
size[x] = recy[x];
if (son[x][0]) size[x] += size[son[x][0]];
if (son[x][1]) size[x] += size[son[x][1]];
}
}
void connect(int x, int y, int z){
if (x) f[x] = y;
if (y) son[y][z] = x;
}
void rotate(int x){
int fa = f[x], ffa = f[fa], m = get(x), n = get(fa);
connect(son[x][m ^ 1], fa, m);
connect(fa, x, m ^ 1);
connect(x, ffa, n);
pushup(fa); pushup(x);
}
void splay(int x, int goal){
while (f[x] != goal){
int fa = f[x];
if (f[fa] != goal) rotate(get(x) == get(fa) ? fa : x);
rotate(x);
}
if (!goal) rt = x;
}
void insert(int x){
if (!rt){
val[rt = ++sz] = x;
size[rt] = recy[rt] = 1;
f[rt] = son[rt][0] = son[rt][1] = 0;
return;
}
int now = rt, fa = 0;
while (1){
if (val[now] == x){
++recy[now];
pushup(now); pushup(fa);
splay(now, 0);
return;
}
fa = now, now = son[now][x > val[now]];
if (!now){
val[now = ++sz] = x;
size[now] = recy[now] = 1;
son[now][0] = son[now][1] = 0;
f[now] = fa;
if (fa) son[fa][x > val[fa]] = now;
pushup(fa);
splay(now, 0);
return;
}
}
}
int find(int k){
int sum = 0, now = rt;
while (1){
if (k < val[now]) now = son[now][0]; else{
sum += size[son[now][0]];
if (k == val[now]){ splay(now, 0); return sum + 1; }
sum += recy[now]; now = son[now][1];
}
}
}
int kth(int k){
int now = rt;
while (1){
if (k <= size[son[now][0]]) now = son[now][0]; else
if (k <= size[son[now][0]] + recy[now]) { splay(now, 0); return val[now]; }else
k -= size[son[now][0]] + recy[now], now = son[now][1];
}
}
int pre(){
int now = son[rt][0];
while (son[now][1]) now = son[now][1];
return now;
}
int nxt(){
int now = son[rt][1];
while (son[now][0]) now = son[now][0];
return now;
}
void del(int k){
int no_use = find(k);
if (recy[rt] > 1){ --recy[rt]; pushup(rt); return; }
if (!son[rt][0] && !son[rt][1]){ clear(rt); rt = 0; return; }
if (!son[rt][0]){ int tmp = rt; f[rt = son[rt][1]] = 0; clear(tmp); return; }
if (!son[rt][1]){ int tmp = rt; f[rt = son[rt][0]] = 0; clear(tmp); return; }
int tmp = rt, left = pre();
splay(left, 0);
connect(son[tmp][1], left, 1);
clear(tmp);
pushup(left);
}
int main(){
int M = read();
while (M--){
int opt = read(), k = read();
if (opt == 1) insert(k); else
if (opt == 2) del(k); else
if (opt == 3) printf("%d\n", find(k)); else
if (opt == 4) printf("%d\n", kth(k)); else
if (opt == 5){ insert(k); printf("%d\n", val[pre()]); del(k); }
if (opt == 6){ insert(k); printf("%d\n", val[nxt()]); del(k); }
}
return 0;
}
12、Splay2
#include <bits/stdc++.h>
#define maxn 100010
using namespace std;
int sz, rt, size[maxn], f[maxn], son[maxn][2], val[maxn], q[maxn], tag[maxn], n, m;
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
int get(int k){ return son[f[k]][1] == k; }
void connect(int x, int y, int z){
if (x) f[x] = y;
if (y) son[y][z] = x;
}
void pushup(int x){
if (x){
size[x] = 1;
if (son[x][0]) size[x] += size[son[x][0]];
if (son[x][1]) size[x] += size[son[x][1]];
}
}
void pushdown(int x){
if (tag[x]){
tag[son[x][0]] ^= 1;
tag[son[x][1]] ^= 1;
swap(son[x][0], son[x][1]);
tag[x] = 0;
}
}
void rotate(int x){
int fa = f[x], ffa = f[fa], m = get(x), n = get(fa);
connect(son[x][m ^ 1], fa, m);
connect(fa, x, m ^ 1);
connect(x, ffa, n);
pushup(fa); pushup(x);
}
void splay(int x, int goal){
int len = 0;
for (int i = x; i; i = f[i]) q[++len] = i;
for (int i = len; i; --i) pushdown(q[i]);
while (f[x] != goal){
int fa = f[x];
if (f[fa] != goal) rotate(get(x) == get(fa) ? fa : x);
rotate(x);
}
if (!goal) rt = x;
}
void insert(int k){
int now = rt, fa = 0;
while (now) fa = now, now = son[now][k > val[now]];
val[now = ++sz] = k;
size[now] = 1, f[now] = fa;
son[now][0] = son[now][1] = 0;
if (fa) son[fa][k > val[fa]] = now;
pushup(fa);
splay(now, 0);
}
int kth(int k){
int now = rt;
while (1){
pushdown(now);
if (k <= size[son[now][0]]) now = son[now][0]; else
if (k <= size[son[now][0]] + 1) return now; else
k -= size[son[now][0]] + 1, now = son[now][1];
}
}
void work(int l, int r){
l = kth(l), r = kth(r + 2);
splay(l, 0); splay(r, l);
tag[son[r][0]] ^= 1;
}
void write(int now){
pushdown(now);
if (son[now][0]) write(son[now][0]);
if (val[now] > 1 && val[now] < n + 2) printf("%d ", val[now] - 1);
if (son[now][1]) write(son[now][1]);
}
int main(){
n = read(), m = read();
for (int i = 1; i <= n + 2; ++i) insert(i);
while (m--){
int l = read(), r = read();
work(l, r);
}
write(rt);
return 0;
}
13、fhq Treap1
#include <bits/stdc++.h>
#define maxn 100010
using namespace std;
int sz, val[maxn], key[maxn], size[maxn], son[maxn][2], rt;
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
int addnode(int k){
val[++sz] = k, key[sz] = rand(), size[sz] = 1;
return sz;
}
void pushup(int x){ size[x] = size[son[x][0]] + size[son[x][1]] + 1; }
int kth(int now, int k){
while (1){
if (k <= size[son[now][0]]) now = son[now][0]; else
if (k <= size[son[now][0]] + 1) return now; else
k -= size[son[now][0]] + 1, now = son[now][1];
}
}
void split(int now, int w, int &u, int &v){
if (!now) u = v = 0; else{
if (val[now] <= w) u = now, split(son[now][1], w, son[u][1], v); else
v = now, split(son[now][0], w, u, son[v][0]);
pushup(now);
}
}
int merge(int u, int v){
if (!u || !v) return u + v;
if (key[u] >= key[v]){
son[u][1] = merge(son[u][1], v);
pushup(u);
return u;
} else{
son[v][0] = merge(u, son[v][0]);
pushup(v);
return v;
}
}
int main(){
srand(time(0));
int M = read();
while (M--){
int opt = read(), k = read(), x, y, z;
if (opt == 1){
split(rt, k, x, y);
rt = merge(merge(x, addnode(k)), y);
} else
if (opt == 2){
split(rt, k, x, y); split(x, k - 1, x, z);
rt = merge(merge(x, merge(son[z][0], son[z][1])), y);
} else
if (opt == 3){
split(rt, k - 1, x, y);
printf("%d\n", size[x] + 1);
rt = merge(x, y);
} else
if (opt == 4) printf("%d\n", val[kth(rt, k)]); else
if (opt == 5){
split(rt, k - 1, x, y);
printf("%d\n", val[kth(x, size[x])]);
rt = merge(x, y);
} else{
split(rt, k, x, y);
printf("%d\n", val[kth(y, 1)]);
rt = merge(x, y);
}
}
return 0;
}
14、fhq Treap2
#include <bits/stdc++.h>
#define maxn 100010
using namespace std;
int sz, rt, n, m, val[maxn], size[maxn], key[maxn], tag[maxn], son[maxn][2];
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
int addnode(int x){
val[++sz] = x, key[sz] = rand() * rand(), size[sz] = 1;
return sz;
}
void pushup(int x){ size[x] = size[son[x][0]] + size[son[x][1]] + 1; }
void pushdown(int x){
if (tag[x]){
tag[son[x][0]] ^= 1, tag[son[x][1]] ^= 1;
swap(son[x][0], son[x][1]);
tag[x] = 0;
}
}
void split(int now, int w, int &u, int &v){
if (!now) u = v = 0; else{
pushdown(now);
if (w <= size[son[now][0]]) v = now, split(son[now][0], w, u, son[v][0]); else
u = now, split(son[now][1], w - size[son[now][0]] - 1, son[u][1], v);
pushup(now);
}
}
int merge(int u, int v){
if (!u || !v) return u + v;
if (key[u] >= key[v]){
pushdown(u);
son[u][1] = merge(son[u][1], v);
pushup(u);
return u;
} else{
pushdown(v);
son[v][0] = merge(u, son[v][0]);
pushup(v);
return v;
}
}
void write(int now){
if (!now) return;
pushdown(now);
write(son[now][0]);
printf("%d ", val[now]);
write(son[now][1]);
}
int main(){
srand(time(0));
n = read(), m = read();
for (int i = 1; i <= n; ++i) rt = merge(rt, addnode(i));
while (m--){
int l = read(), r = read(), x, y, z;
split(rt, r, x, y);
split(x, l - 1, x, z);
tag[z] ^= 1;
rt = merge(merge(x, z), y);
}
write(rt);
return 0;
}
本文汇总了各类经典算法的模板实现,包括数论、计算几何、图论、字符串处理等多个方面,为读者提供了丰富的算法实现案例。
6063

被折叠的 条评论
为什么被折叠?



