模板整理

本文汇总了各类经典算法的模板实现,包括数论、计算几何、图论、字符串处理等多个方面,为读者提供了丰富的算法实现案例。

因为自己还得再写一遍,大部分模板得先鸽鸽鸽
注:算法名称上搞了对应模板的传送门

数论

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;
}
内容概要:本文介绍了ENVI Deep Learning V1.0的操作教程,重点讲解了如何利用ENVI软件进行深度学习模型的训练与应用,以实现遥感图像中特定目标(如集装箱)的自动提取。教程涵盖了从数据准备、标签图像创建、模型初始化与训练,到执行分类及结果优化的完整流程,并介绍了精度评价与通过ENVI Modeler实现一键化建模的方法。系统基于TensorFlow框架,采用ENVINet5(U-Net变体)架构,支持通过点、线、面ROI或分类图生成标签数据,适用于多/高光谱影像的单一类别特征提取。; 适合人群:具备遥感图像处理基础,熟悉ENVI软件操作,从事地理信息、测绘、环境监测等相关领域的技术人员或研究人员,尤其是希望将深度学习技术应用于遥感目标识别的初学者与实践者。; 使用场景及目标:①在遥感影像中自动识别和提取特定地物目标(如车辆、建筑、道路、集装箱等);②掌握ENVI环境下深度学习模型的训练流程与关键参数设置(如Patch Size、Epochs、Class Weight等);③通过模型调优与结果反馈提升分类精度,实现高效自动化信息提取。; 阅读建议:建议结合实际遥感项目边学边练,重点关注标签数据制作、模型参数配置与结果后处理环节,充分利用ENVI Modeler进行自动化建模与参数优化,同时注意软硬件环境(特别是NVIDIA GPU)的配置要求以保障训练效率。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值