OI模板复习

本文涵盖多种核心算法与数据结构的实现,包括数学算法如最大公约数、扩展最大公约数、快速幂等,数据结构如堆、树状数组、线段树等,以及经典算法如最小生成树、匈牙利算法、网络流等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数学有关的东西

gcd:

可以交在传送门洛谷2152拿完20分就跑23333(正解需要高精+一堆处理)

#include <cstdio>
#include <cstring>
#include <algorithm>

long long a, b;

long long gcd(long long a, long long b) {
    if (b == 0) return (a);
    return (gcd(b, a % b));
}

int main () {
    scanf("%lld %lld", &a, &b);
    printf("%lld", gcd(a, b));
    return 0;
}

exgcd:

传送门洛谷1082

#include <cstdio>
#include <cstring>
#include <algorithm>

int a, b, x, y;

void exgcd(int a, int b, int &x, int &y) {
    if (b == 0) {
        x = 1;
        y = 0;
        return;
    }
	exgcd(b, a % b, x, y);
	int t = x;
	x = y;
	y = t - a / b * y;
}

int main () {
    scanf("%d %d", &a, &b);
    exgcd(a, b, x, y);
	x = ((x % b) + b ) % b;
	printf("%d", x);
    return 0;
}

快速幂:

传送门洛谷1226

#include <cstdio>
#include <cstring>
#include <algorithm>

long long b, p, k;

long long qpow(long long base, long long v, long long mod) {
	long long ans = 1;
	while (v > 0) {
		if (v & 1) ans = (ans * base) % mod;
		base = (base * base) % mod;
		v = v >> 1;
	}
	return (ans);
}
int main () {
	scanf("%lld %lld %lld", &b, &p, &k);
	printf("%lld^%lld mod %lld=%lld", b, p, k, qpow(b, p, k));
	
	return 0;
}

欧拉筛法:

传送门洛谷3383

#include <cstdio>
#include <cstring>
#include <algorithm>

const int maxn = 10000000 + 5000;
int n, m;
int prime[maxn], isp[maxn];
int ptot = 0;
int x;
int main () {
	scanf("%d %d", &n, &m);
	for (int i = 2; i <= n; i++) isp[i] = 1;
	for (int i = 2; i <= n; i++) {
		if (isp[i]) {
			ptot++;
			prime[ptot] = i;
		}
		long long k;
		for (int j = 1; j <= ptot && (k = 1ll * prime[j] * i) <= n; j++) {
			isp[k] = 0;
			if (!(i % prime[j])) break;
		}
	}
	for (int i = 1; i <= m; i++) {
		scanf("%d", &x);
		if (isp[x]) printf("Yes\n");
		else printf("No\n");
	}
	return 0;
} 

最长不上升子序列:

传送门洛谷2757

#include <cstdio>
#include <cstring>
#include <algorithm>
const int maxn = 300000 + 500;
int n;
int a[maxn];
int d[maxn];
int len = 0;
int x;
int ans;

int main () {
	d[0] = 0x7fffffff;
	n = 1;
	while (scanf("%d", &a[n]) == 1) {
		if (a[n] <= d[len]) {
			len++;
			d[len] = a[n];
		} else {
			int l = 0, r = len; 
			while (l <= r) {
				int mid = (l + r) >> 1;
				if (d[mid] >= a[n]) {
					l = mid + 1;
					ans = mid;
				}  else {
					r = mid - 1;
				}
			}
			d[ans+1] = a[n];
		}
		n++;
	}
	printf("%d\n", len);
	memset(d, 0, sizeof(d));
	// printf("%d", n);
	n--;
	len = 0;
	for (int i = 1; i <= n; i++) {
		if (a[i] > d[len]) {
			len++;
			d[len] = a[i];
		} else {
			int l = 0, r = len;
			while (l <= r) {
				int mid = (l + r) >> 1;
				if (d[mid] < a[i]) {
					l = mid + 1;
					ans = mid;
				} else {
					r = mid - 1;
				}
			}
			d[ans+1] = a[i];
		}
	}
	printf("%d", len);
	return 0;
}

高精度加法,读入,输出:

传送门洛谷1601
注意进位时要用+=

#include <cstdio>
#include <cstring>
#include <algorithm>

int tt[1000];
struct bigint {
	int num;
	int a[1000];
	void print() {
		for (int j = num; j >= 1; j--) {
			printf("%d", a[j]);
		}
		printf("\n");
	}
	void readint() {
		memset(tt, 0, sizeof(tt));
		char c = getchar();
		num = 0;
		while (c < '0' || c > '9') c = getchar();
		while (c >= '0' && c <= '9') {
			num++;
			tt[num] = c - '0';
			c = getchar();
		}
		for (int i = 1; i <= num; i++) 
			a[i] = tt[num - i + 1];
	}
	void clear0() {
		num = 0;
		memset(a, 0, sizeof(a));
	}
	void clear1() {
		num = 1;
		memset(a, 0, sizeof(a));
		a[1] = 1;
	}
};

bigint aa, bb;
bigint cc;
bigint operator + (bigint xx, bigint yy) {
	bigint cc;
	cc.clear0();
	cc.num = std :: max(xx.num, yy.num);
	for (int i = 1; i <= cc.num; i++) {
		cc.a[i] += xx.a[i] + yy.a[i];
		if (cc.a[i] >= 10) {
			cc.a[i+1] += cc.a[i] / 10;
			cc.a[i] = cc.a[i] % 10;
 		}
	}
	if (cc.a[cc.num + 1] == 0) return (cc);
	cc.num++;
	while (cc.a[cc.num] >= 10) {
		cc.a[cc.num+1] += cc.a[cc.num] / 10;
		cc.a[cc.num] = cc.a[cc.num] % 10;
	}
	return (cc);
}

int main () {
	aa.readint();
	bb.readint();
	// aa.print();
	// bb.print();
	cc = aa + bb;
	cc.print();
	return 0;
}

矩阵快速幂:

传送门洛谷3390
手一抖就把乘号打成了加号

#include <cstdio>
#include <cstring>
#include <algorithm>

const int maxn = 110;
const long long mod = 1e9 + 7;
int n;
struct data {
	long long a[maxn][maxn];
	void clear0(void) {
		memset(a, 0, sizeof(a));
	}
	void clear1(void) {
		memset(a, 0, sizeof(a));
		for (int i = 1; i <= n; i++) a[i][i] = 1; 
	}
	void print() {
		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= n; j++) printf("%d ", a[i][j]);
			printf("\n");
		}
	}
};
long long k;
data aa;
data ans;
data operator * (data xx, data yy) {
	data cc;
	cc.clear0();
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++) 
			for (int k = 1; k <= n; k++) cc.a[i][j] = (cc.a[i][j] + xx.a[i][k] * yy.a[k][j]) % mod;
	return (cc);
}

data qpow(data aa, long long v, long long mod) {
	data ans;
	ans.clear1();
	while (v > 0) {
		if (v & 1) ans = ans * aa;
		v = v >> 1;
		aa = aa * aa;
	}
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++) ans.a[i][j] %= mod;
	return ans;
}

int main () {
	scanf("%d %lld", &n, &k);
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++) {
			scanf("%d", &aa.a[i][j]);
			aa.a[i][j] %= mod;
		}
	ans = qpow(aa, k, mod);
	ans.print();
	return 0;
}
 

数据结构:

class Heap{
    // big first heap;
    public int[] data = new int[100000];
    public int total = 0;

    public void insert(int x) {
        total++;
        data[total] = x;
        int cur = total;
        while (cur > 1) {
            int father = cur >> 1;
            if (data[father] < data[cur]) {
                int c = data[father];
                data[father] = data[cur];
                data[cur] = c;
                cur = father;
            } else {
                break;
            }
        }
    }

    public int top() {
        return data[1];
    }

    public void pop() {
        data[1] = data[total];
        total--;
        int cur = 1;
        while (true) {
            int son1 = cur * 2;
            int son2 = cur * 2 + 1;
            if (son1 > total) {
                break;
            } else if (son2 > total) {
                if (data[cur] < data[son1]) {
                    int c = data[cur];
                    data[cur] = data[son1];
                    data[son1] = c;
                }
                cur = son1;
            } else {
                int curSon = 0;
                if (data[son1] > data[son2]) {
                    curSon = son1;
                } else {
                    curSon = son2;
                }
                if (data[cur] < data[curSon]) {
                    int c = data[cur];
                    data[cur] = data[curSon];
                    data[curSon] = c;
                }
                cur = curSon;
            }
        }
    }

}




树状数组:

传送门洛谷3374

#include <cstdio>
#include <cstring>
#include <algorithm>

const int maxn = 550000;
int c[maxn];
int n, m;
int x;
int odd, y;
inline int lowbit(int x) {
	return (x & (-x));
}

void change(int x, int z) {
	while (x <= n) {
		c[x] += z;
		x += lowbit(x);
	}
}

long long xfind(int x) {
	long long ans = 0;
	while (x > 0) {
		ans += c[x];
		x -= lowbit(x);
	}
	return (ans);
}

int main () {
	scanf("%d %d", &n, &m);
	for (int i = 1; i <= n; i++) {
		scanf("%d", &x);
		change(i, x);
	}
	for (int i = 1; i <= m; i++) {
		scanf("%d %d %d", &odd, &x, &y);
		if (odd == 1) {
			change(x, y);
		} else {
			printf("%lld\n", xfind(y) - xfind(x-1));
		}
	}
	
	return 0;
}

线段树:

传送门洛谷3372
手抖数组没开三倍,,

#include <cstdio>
#include <cstring>
#include <algorithm>

const int maxn = 110000;
struct data {
	int l, r;
	long long sum;
	long long lazy;
};
data p[maxn * 3];
int a[maxn];
int n, m;
int od, x, y, z;
void build(int x, int l, int r) {
	p[x].l = l;
	p[x].r = r;
	if (p[x].l == p[x].r) {
		p[x].sum = a[l];
		return;
	}
	int mid = (l + r) >> 1;
	build(2 * x, l, mid);
	build(2 * x + 1, mid + 1, r);
	p[x].sum = p[2 * x].sum + p[2 * x + 1].sum;
}

void update(int x) {
	p[x].sum += p[x].lazy * (p[x].r - p[x].l + 1);
	if (p[x].l == p[x].r) {
		p[x].lazy = 0;
		return;
	}
	p[2 * x].lazy += p[x].lazy;
	p[2 * x + 1].lazy += p[x].lazy;
	p[x].lazy = 0;
}

void change(int x, int l, int r, int z) {
	if (p[x].l == l && p[x].r == r) {
		p[x].lazy += z;
		return;
	}
	if (p[x].lazy) update(x);
	int mid = (p[x].l + p[x].r) >> 1;
	if (r <= mid) change(2 * x, l, r, z);
	else if (l > mid) change(2 * x + 1, l, r, z);
	else {
		change(2 * x, l, mid, z);
		change(2 * x + 1, mid + 1, r, z);
	}
	p[x].sum = (p[2 * x].sum + p[2 * x + 1].sum + p[2 * x].lazy * (p[2 * x].r - p[2 * x].l + 1) + p[2 * x + 1].lazy * (p[2 * x + 1].r - p[2 * x + 1].l + 1));	
}

long long xfind(int x, int l, int r) {
	if (p[x].lazy) update(x);
	if (p[x].l == l && p[x].r == r) {
		return (p[x].sum);
	}
	int mid = (p[x].l + p[x].r) >> 1;
	if (r <= mid) return (xfind(2 * x, l, r));
	else if (l > mid) return (xfind(2 * x + 1, l, r));
	else return (xfind(2 * x, l, mid) + xfind(2 * x + 1, mid + 1, r));
}

int main () {
	scanf("%d %d", &n, &m);
	for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
	build(1, 1, n);
	for (int i = 1; i <= m; i++) {
		scanf("%d %d %d", &od, &x, &y);
		if (od == 1) {
			scanf("%d", &z);
			change(1, x, y, z);
		} else {
			printf("%lld\n", xfind(1, x, y));
		}
	}
	return 0;
}
 

单调队列:

传送门洛谷1886
改了一个世纪,,感觉单调队列有点虚,,错误点:

  • q1和q2数组存储的应该是下标而非数据,处理过程中弄混
  • 在前移队列尾指针时忘记控制尾指针小于头指针
#include <cstdio>
#include <cstring>
#include <algorithm>

const int maxn = 1e6 + 500;
const int inf = 0x7fffffff;
int q1[maxn];		//	min
int q2[maxn];		//	max
int a[maxn];
int q1h = 1, q1t = 1;
int q2h = 1, q2t = 1;
int n, k;
int main () {
	freopen("window.in", "r", stdin);
	freopen("window.out", "w", stdout);
	scanf("%d %d", &n, &k);
	q2[0] = 0;
	q1[0] = 0;
	for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
	q1[1] = 1;
	for (int i = 2; i <= k; i++) {
		while (a[q1[q1t]] >= a[i] && q1t >= q1h) q1t--;
		q1t++;
		q1[q1t] = i;
	}
	printf("%d ", a[q1[1]]);
	for (int i = k + 1; i <= n; i++) {
		while (a[q1[q1t]] >= a[i] && q1t >= q1h) q1t--;
		q1t++;
		q1[q1t] = i;
		while (q1[q1h] <= i - k) q1h++;
		printf("%d ", a[q1[q1h]]);
	}
	q2[1] = 1;
	for (int i = 2; i <= k; i++) {
		while (a[q2[q2t]] <= a[i] && q2t >= q2h) q2t--;
		q2t++;
		q2[q2t] = i;
	}
	printf("\n%d ", a[q2[1]]);
	for (int i = k + 1; i <= n; i++) {
		while(a[q2[q2t]] <= a[i] && q2t >= q2h) q2t--;
		q2t++;
		q2[q2t] = i;
		while (q2[q2h] <= i - k) q2h++;
		printf("%d ", a[q2[q2h]]);
	}
	return 0;
}

第二次做就熟悉了好多
传送门洛谷1440

#include <cstdio>
#include <cstring>
#include <algorithm>

const int maxn = 2000000 + 5000;
int q1[maxn];
int q1h = 1, q1t = 1;
int n, m;
int a[maxn];

int main () {
	scanf("%d %d", &n, &m);
	for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
	printf("0\n");
	q1[1] = 1;
	printf("%d\n", a[1]);
	for (int i = 2; i <= m; i++) {
		while (a[q1[q1t]] >= a[i] && q1t >= q1h) q1t--;
		q1t++;
		q1[q1t] = i;
		printf("%d\n", a[q1[1]]);
	}
	for (int i = m + 1; i < n; i++) {
		while (a[q1[q1t]] >= a[i] && q1t >= q1h) q1t--;
		q1t++;
		q1[q1t] = i;
		while (q1[q1h] <= i - m) q1h++;
		printf("%d\n", a[q1[q1h]]);
	}
	return 0;
}

并查集:

传送门洛谷3367

#include <cstdio>
#include <cstring>
#include <algorithm>

const int maxn = 10000 + 500;
int father[maxn];
int x, y, od;
int n, m;

int getfather(int x) {
	if (father[x] == x) return (x);
	return (father[x] = getfather(father[x]));
}

int main () {
	scanf("%d %d", &n, &m);
	for (int i = 1; i <= n; i++) father[i] = i;
	for (int i = 1; i <= m; i++) {
		scanf("%d %d %d", &od, &x, &y);
		if (od == 1) {
			int tx = getfather(x);
			int ty = getfather(y);
			if (tx == ty) continue;
			father[tx] = ty;
		} else {
			int tx = getfather(x);
			int ty = getfather(y);
			if (tx == ty) printf("Y\n");
			else printf("N\n");
		}
	}
	
	return 0;
}

平衡树:

传送门洛谷3369

#include <cstdio>
#include <cstring>
#include <algorithm>

const int maxn = 100000 + 5000;
int size[maxn], left[maxn], right[maxn], val[maxn];
int n, m;
int tot = 0;
int t = 0;
int oop, key;

void right_rotate(int &t) {
	int k = left[t];
	left[t] = right[k];
	right[k] = t;
	size[k] = size[t];
	size[t] = size[left[t]] + size[right[t]] + 1;
	t = k;
}
void left_rotate(int &t) {
	int k = right[t];
	right[t] = left[k];
	left[k] = t;
	size[k] = size[t];
	size[t] = size[left[t]] + size[right[t]] + 1;
	t = k;
}
void maintain(int &t, bool flag) {
	if (flag) {
		if (size[right[right[t]]] > size[left[t]]) {
			left_rotate(t);
		} else if (size[left[right[t]]] > size[left[t]]) {
			right_rotate(right[t]);
			left_rotate(t);
		} else return;
	} else {
		if (size[left[left[t]]] > size[right[t]]) {
			right_rotate(t);
		} else if (size[right[left[t]]] > size[right[t]]) {
			left_rotate(left[t]);
			right_rotate(t);
		}  else return;
	}
	maintain(left[t], 0);
	maintain(right[t], 1);
	maintain(t, 0);
	maintain(t, 1);
}
void insert1(int &t, int v) {
	if (t == 0) {
		tot++;
		t = tot;
		size[t] = 1;
		val[t] = v;
		left[t] = 0;
		right[t] = 0;
	} else {
		size[t]++;
		if (v < val[t]) {
			insert1(left[t], v); 
		} else {
			insert1(right[t], v);
		}
		maintain(t, v >= val[t]);
	}
}

int delete2(int &t, int v) {
	int cur = 0;
	size[t]--;
	if (v == val[t] || (v > val[t] && right[t] == 0) || (v < val[t] && left[t] == 0)) {
		cur = val[t];
		if (left[t] == 0 || right[t] == 0) {
			t = left[t] + right[t];
		} else {
			val[t] = delete2(left[t], v + 1);
		}
	} else if (v < val[t]) cur = delete2(left[t], v);
	else cur = delete2(right[t], v);
	return (cur);
}

int rank3(int &t, int v) {
	if (t == 0) return (1);
	if (val[t] >= v) {
		return (rank3(left[t], v));
	} else if (val[t] < v) {
		return (rank3(right[t], v) + size[left[t]] + 1);
	}
}

int find4(int &t, int v) {
	if (size[left[t]] + 1 == v) return (val[t]);
	else if (size[left[t]] + 1 < v) return (find4(right[t],v - size[left[t]] - 1));
	else return (find4(left[t], v));
}

int pre5(int &t, int v) {
	if (t == 0) return (-1);
	if (v <= val[t]) {
		return (pre5(left[t], v));
	} else {
		int cur = pre5(right[t], v);
		if (cur == -1) return (val[t]);
		return (cur);
	}
}

int succ6(int &t, int v) {
	if (t == 0) return (-1);
	if (v >= val[t]) {
		return (succ6(right[t], v)); 
	} else {
		int cur = succ6(left[t], v);
		if (cur == -1) return (val[t]);
		return (cur);
	}
}


int main () {
	scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d %d", &oop, &key);
        if (oop == 1) insert1(t, key);
        if (oop == 2) delete2(t, key);
        if (oop == 3) printf("%d\n", rank3(t,key));
        if (oop == 4) printf("%d\n", find4(t, key));
        if (oop == 5) printf("%d\n", pre5(t, key));
        if (oop == 6) printf("%d\n", succ6(t, key));
    }
	
	return 0;
}

算法

最小生成树

传送门洛谷3366

#include <cstdio>
#include <cstring>
#include <algorithm>

const int maxn = 6000;
const int maxm = 210000;
struct data {
	int from;
	int to;
	int val;
};
int father[maxn];
data p[maxm];
int n, m;
int x, y, z;
long long ans = 0;
int cur;
bool cmp(data aa, data bb) {
	return (aa.val < bb.val);
}

int getfather(int x) {
	if (father[x] == x) return (x);
	return (father[x] = getfather(father[x]));
}

int main () {
	scanf("%d %d", &n, &m);
	cur = n;
	for (int i = 1; i <= n; i++) father[i] = i;
	for (int i = 1; i <= m; i++) {
		scanf("%d %d %d", &p[i].from, &p[i].to, &p[i].val);
	}
	std :: sort(p + 1, p + m + 1, cmp);
	for (int i = 1; i <= m; i++) {
		int tx = getfather(p[i].from);
		int ty = getfather(p[i].to);
		if (tx != ty) {
			cur--;
			father[tx] = ty;
			ans += p[i].val;
		}
	}
	if (cur > 1) printf("orz");
	else printf("%lld", ans);
	return 0;
}

匈牙利算法:

传送门洛谷3386

#include <cstdio>
#include <cstring>
#include <algorithm>

const int maxn = 2200;
int line[maxn][maxn];
int flag[maxn];
int vis[maxn];
int n, m, e;
int ans = 0;
int x, y;

bool xfind(int x) {
	for (int j = 1; j <= m; j++) {
		if (line[x][j] && flag[j] == 0) {
			flag[j] = 1;
			if (vis[j] == 0 || xfind(vis[j])) {
				vis[j] = x;
				return 1;
			}
		}
	}
	return 0;
}

int main () {
	scanf("%d %d %d", &n, &m, &e);
	for (int i = 1; i <= e; i++) {
		scanf("%d %d", &x, &y);
		line[x][y] = 1;
	}
	for (int i = 1; i <= n; i++) {
		memset(flag, 0, sizeof(flag));
		if (xfind(i)) ans++;
	}
	printf("%d", ans);
	return 0;
}

SPFA:

传送门

#include <cstdio>
#include <cstring>
#include <algorithm>

const int maxn = 15000;
const int maxm = 500000 + 5000;
const int inf = 0x7fffffff;
int dis[maxn], que[maxn], vis[maxn];
int last[maxn], pre[maxm], other[maxm], val[maxm];
int tot = 1;
int n, m, s;
int x, y, z;

void add(int x, int y, int z) {
	tot++;
	pre[tot] = last[x];
	last[x] = tot;
	other[tot] = y;
	val[tot] = z;
}
void spfa(int s) {
	que[1] = s;
	for (int i = 1; i <= n; i++) dis[i] = inf;
	dis[s] = 0;
	int h = 0, t = 1;
	while (h != t) {
		h = (h + 1) % maxn;
		int cur = que[h];
		vis[cur] = 0;
		for (int p = last[cur]; p; p = pre[p]) {
			int q = other[p];
			if (dis[q] > dis[cur] + val[p]) {
				dis[q] = dis[cur] + val[p];
				if (vis[q] == 0) {
					vis[q] = 1;
					t = (t + 1) % maxn;
					que[t] = q;
				}
			}
		}
	}
}
int main () {
	scanf("%d %d %d", &n, &m, &s);
	for (int i = 1; i <= m; i++) {
		scanf("%d %d %d", &x, &y, &z);
		add(x, y, z);
	}
	spfa(s);
	for (int i = 1; i <= n; i++) printf("%d ", dis[i]);
	
	return 0;
}

堆+dijkstra:

传送门洛谷3371

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
const int maxn = 12000;
const int maxm = 550000;
const int inf = 0x7fffffff;
int n, m;
int s;
int last[maxn], pre[maxm], other[maxm], len[maxm];
int dis[maxn];
bool vis[maxn];
int tot = 0;
int x, y, z;
struct point{
	int dis;
	int num;
	point(int num, int dis) : dis(dis), num(num) {}
};
bool operator < (point aa, point bb) {
	return (aa.dis > bb.dis);
}

std :: priority_queue <point> q1;

void add(int x, int y, int z) {
	tot++;
	pre[tot] = last[x];
	last[x] = tot;
	other[tot] = y;
	len[tot] = z;
}

void dijkstra(int s) {
	for (int i = 1; i <= n; i++) {
		dis[i] = inf;
		q1.push(point(i, dis[i]));
	}
	dis[s] = 0;
	q1.push(point(s, dis[s]));
	while (!q1.empty()) {
		point kkk = q1.top();
		q1.pop();
		if (kkk.dis == inf) return;
		if (vis[kkk.num]) continue;
		vis[kkk.num] = 1;
		for (int p = last[kkk.num]; p; p = pre[p]) {
			int q = other[p];
			if (dis[q] > dis[kkk.num] + len[p]) {
				dis[q] = dis[kkk.num] + len[p];
				q1.push(point(q, dis[q]));
			}
		}
	}
 	
}

int main () {
	scanf("%d %d %d", &n, &m, &s);
	for (int i = 1; i <= m; i++) {
		scanf("%d %d %d", &x, &y, &z);
		add(x, y, z);
	}
	dijkstra(s);
	for (int i = 1; i <= n; i++) printf("%d ", dis[i]);
	return 0;
}

KMP:

传送门洛谷3375

#include <cstdio>
#include <cstring>
#include <algorithm>

const int maxn = 1100000;
const int maxm = 1100;
int next[maxm];
char s1[maxn];
char s2[maxm];



int main () {
	scanf("%s %s", s1, s2);
	int len1 = strlen(s1);
	int len2 = strlen(s2);
	for (int i = 1,  p = 0; i < len2; i++) {
		while (s2[i] != s2[p] && p > 0) p = next[p-1];
		if (s2[i] == s2[p]) p++;
		next[i] = p;
	}
	for (int i = 0, p = 0; i < len1; i++) {
		while (s1[i] != s2[p] && p > 0) p = next[p-1];
		if (s1[i] == s2[p]) p++;
		if (p == len2) {
			printf("%d\n", i - len2 + 2);
			p = next[p-1];
		}
	}
	for (int i = 0; i < len2; i++) printf("%d ", next[i]);
	return 0;
}

倍增LCA:

传送门洛谷3379

#include <cstdio>
#include <cstring>
#include <algorithm>

const int maxn = 550000;
int n, m, s;
int last[maxn], pre[maxn * 2], other[maxn * 2];
int jump[maxn][30];
int dis[maxn];
int tot = 0;
int x, y;

void add(int x, int y) {
	tot++;
	pre[tot] = last[x];
	last[x] = tot;
	other[tot] = y;
}
void dfs(int x, int come) {
	jump[x][0] = come;
	dis[x] = dis[come] + 1;
	for (int p = last[x]; p; p = pre[p]) {
		int q = other[p];
		if (q == come) continue;
		dfs(q, x);
	}
}

int lca(int x, int y) {
	if (dis[x] < dis[y]) std :: swap(x, y);
	if (dis[x] != dis[y]) { 
		for (int j = 25; j >= 0; j--) 
			if (dis[jump[x][j]] > dis[y]) x = jump[x][j];
		x = jump[x][0];
	}
	if (x == y) return (x);
	for (int j = 25; j >= 0; j--) {
		if (jump[x][j] != jump[y][j]) {
			x = jump[x][j];
			y = jump[y][j];
		}
	}
	return jump[x][0];
}

int main () {
	scanf("%d %d %d", &n, &m, &s);
	for (int i = 1; i < n; i++) {
		scanf("%d %d", &x, &y);
		add(x, y);
		add(y, x);
	}
	dfs(s, 0);
	for (int i = 1; i <= 25; i++) 
		for (int j = 1; j <= n; j++) 
			jump[j][i] = jump[jump[j][i-1]][i-1];
	for (int i = 1; i <= m; i++) {
		scanf("%d %d", &x, &y);
		printf("%d\n", lca(x, y));
	}
	return 0;
}

Tarjan求环:

传送门洛谷2661

#include <cstdio>
#include <cstring>
#include <algorithm>

const int maxn = 300000;
int next[maxn];
int dfn[maxn], low[maxn], size[maxn], belong[maxn];
bool vis[maxn];
int sta[maxn];
int statot = 0;
int cur = 0;
int tim = 0;
int n;
int ans = 0x7fffffff;


void tarjan(int x) {
	tim++;
	dfn[x] = low[x] = tim;
	statot++;
	vis[x] = 1;
	sta[statot] = x;
	int q = next[x];
	if (!dfn[q]) {
		tarjan(q);
		low[x] = std :: min(low[x], low[q]);
	} else if (vis[q]) {
		low[x] = std :: min(dfn[q], low[x]);
	}
	if (dfn[x] == low[x]) {
		cur++;
		while (sta[statot] != x) {
			belong[sta[statot]] = cur;
			vis[sta[statot]] = 0;
			size[cur]++;
			statot--;
		}
		belong[x] = cur;
		statot--;
		size[cur]++;
	}
}

int main () {
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) scanf("%d", &next[i]);
	for (int i = 1; i <= n; i++) {
		if (!dfn[i]) tarjan(i);
	}
	for (int i = 1; i <= cur; i++) {
		if (size[i] > 1) ans = std :: min(ans, size[i]);
	}
	printf("%d", ans);
	return 0;
}

归并排序:

传送门洛谷1177

#include <cstdio>
#include <cstring>
#include <algorithm>

const int maxn = 100000 + 5000;
int tmp[maxn];
int a[maxn];
int n;


void merg(int *a, int l, int mid, int r) {
	int cur = 1;
	int k1 = l;
	int k2 = mid + 1;
	while (k1 <= mid && k2 <= r) {
		if (a[k1] < a[k2]) {
			tmp[cur] = a[k1];
			cur++;
			k1++;
		} else {
			tmp[cur] = a[k2];
			cur++;
			k2++;
		}
	}
	while (k1 <= mid) {
		tmp[cur] = a[k1];
		cur++;
		k1++;
	}
	while (k2 <= mid) {
		tmp[cur] = a[k2];
		k2++;
		cur++;
	}
	memcpy(a + l, tmp + 1, sizeof(int) * (cur - 1));
}
void m_sort(int *a, int l, int r) {
	if (l < r) {
		int mid = (l + r) >> 1;
		m_sort(a, l, mid);
		m_sort(a, mid + 1, r);
		merg(a, l, mid, r);
	}
}
int main () {
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
	m_sort(a, 1, n);
	for (int i = 1; i <= n; i++) printf("%d ", a[i]);
	return 0;
}

网络流(dinic):

传送门洛谷3376

#include <cstdio>
#include <algorithm>
#include <cstring>
using std :: min;
const int maxm = 200000 + 1000;
const int maxn = 10000 + 500;
int last[maxn], pre[maxm], other[maxm], cap[maxm];
int tot = 1;
int s, t, n, m;
int x, y, z;
int dis[maxn], vis[maxn];
int que[maxn];


void add(int x, int y, int z) {
    tot++;
    pre[tot] = last[x];
    last[x] = tot;
    other[tot] = y;
    cap[tot] = z;
}
bool bfs(void) {
    memset(dis, 0, sizeof(dis));
    memset(vis, 0, sizeof(vis));
    int queh = 0, quet = 1;
    que[1] = s;
    vis[s] = dis[s] = 1;
    while (queh < quet) {
        queh++;
        int cur = que[queh];
        for (int p = last[cur]; p; p = pre[p]) {
            int q = other[p];
            if (cap[p] && !vis[q]) {
                vis[q] = 1;
                dis[q] = dis[cur] + 1;
                quet++;
                que[quet] = q; 
            }
        } 
    }
    return (dis[t] > 0);
}
int dinic(int x, int flow) {
    if (x == t) return (flow);
    int ret = 0;
    for (int p = last[x]; p; p = pre[p]) {
        int q = other[p];
        if (cap[p] && flow && dis[q] == dis[x] + 1) {
            int push = dinic(q, min(cap[p], flow));
            if (!push) dis[q] = 0;
            flow -= push;
            ret += push;
            cap[p] -= push;
            cap[p ^ 1] += push;
        }
    }
    return (ret);
}
int main () {
    scanf("%d %d %d %d", &n, &m, &s, &t);
    for (int i = 1; i <= m; i++) {
        scanf("%d %d %d", &x, &y, &z);
        add(x, y, z);
        add(y, x, 0);
    }
    int ans = 0;
    while (bfs()) {
        ans += dinic(s, 0x7fffffff);
    } 
    printf("%d\n", ans);
    return 0;
}

字符串hash:

传送门洛谷3370

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int mod = 1e7 + 19;
const int base = 31;
const int step = 72;
int hasht[mod];
char s[1600];
int n;
int ans = 0;
char hs[10005][1600];
int tot = 0;
int main () {
    ios_base :: sync_with_stdio(0);
    cin.tie(0);
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> s;
        long long cur = 0;
        int len = strlen(s);
        for (int i = 0; i < len; i++) {
            cur = (cur * base + (int)s[i]) % mod;
        }
        bool ft = 0;
        while (hasht[cur] != 0) {
            if (strcmp(hs[hasht[cur]], s) == 0) {
                ft = 1;
                break;
            }
            cur = (cur + step) % mod;
        }
        if (ft) continue;
        tot++;
        hasht[cur] = tot;
        ans++;
        strcpy(hs[tot], s);
    }    
    cout << ans << endl;
    return 0;
}

快速排序

public void quickSort(int[] a, int left, int right) {
        if (left >= right) return;
        int mid = (left + right) / 2;
        int i = left;
        int j = right;
        int x = a[mid];
        while (i <= j) {
            while (i < right && a[i] < x) i++;
            while (j > left && a[j] > x) j--;
            if (i <= j) {
                int t = a[i];
                a[i] = a[j];
                a[j] = t;
                i++;
                j--;
            }
        }
        quickSort(a, left, j);
        quickSort(a, i, right);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值