算法总结

最短路

SPFA

#include <bits/stdc++.h>

using namespace std;

#define N 10001
#define M 500001 
struct node{
	int to, w, next;
}edge[M];
int cut = 0;
int head[N];
int dis[N];
int n,m,k;
bool vis[N];
queue <int> q;

void ini () {
	fill (dis + 1, dis + N + 1, INT_MAX);
	memset (head, -1, sizeof (head));
}

void add (int u, int v, int w) {//建边 
	cut ++;
	edge[cut].w = w;
	edge[cut].to = v;
	edge[cut].next = head[u];
	head[u] = cut;
}

void SPFA (int x) {
	dis[x] = 0;
	q.push (x);//头入队 
	vis[x] = 1;
	while (! q.empty ()) {
		int u = q.front(); q.pop(); vis[u] = false;
		for (int j = head[u]; ~ j; j = edge[j].next) {//调用邻接表 
			if (dis[edge[j].to] > dis[u] + edge[j].w) {
				dis[edge[j].to] = dis[u] + edge[j].w;//松弛操作 
				if (! vis[edge[j].to]) {//判断标记 
					q.push (edge[j].to);//入队边上的点 
					vis[edge[j].to] = 1;//标记 
				}
			}
		}
	}
} 

int main () {
	
	ini ();
	scanf ("%d %d %d", &n, &m, &k);
	for (int i = 1, u, v, w; i <= m; i ++) {
		scanf ("%d %d %d", &u, &v, &w);
		add (u, v, w);
	}
	SPFA (k);
	for (int i = 1; i <= n; i ++) {
		printf ("%d ", dis[i]);
	}
		
	return 0;
}

Dijkstra(堆优化)

#include <bits/stdc++.h>

using namespace std;

#define N 10001
#define M 500001 
#define P pair<int,int>  
#define Fi first
#define Se second
struct node{
	int to, w, next;
}edge[M];
int cut = 0;
int head[N];
int dis[N];
int n, m, k;
bool vis[N];
priority_queue <P, vector<P>, greater<P> > q;//优先队列 

void ini () {
	fill (dis + 1, dis + N + 1, INT_MAX);
	memset (head, -1, sizeof (head));
}

void add (int u, int v, int w) {
	cut ++;
	edge[cut].w = w;
	edge[cut].to = v;
	edge[cut].next = head[u];
	head[u] = cut;
}

void Dij (int x) {
	dis[x] = 0;
	vis[x] = 1;
	q.push (P (0, x));//头入队 
	while (! q.empty ()) {
		P u = q.top(); q.pop(); vis[u.Se] = 1;
		for (int j = head[u.Se]; ~ j; j = edge[j].next) {//邻接表遍历 
			if (! vis[edge[j].to] && dis[edge[j].to] > dis[u.Se] + edge[j].w) {//判断标记和松弛操作 
				dis[edge[j].to] = dis[u.Se] + edge[j].w;//松弛 
				q.push (P (dis[edge[j].to], edge[j].to));//入队 
			}
		}
	}
} 

int main () {
	
	ini ();
	scanf ("%d %d %d", &n, &m, &k);
	for (int i=1, u, v, w; i <= m; i ++) {
		scanf ("%d %d %d", &u, &v, &w);
		add (u, v, w);
	}
	Dij (k); 
	for (int i = 1; i <= n; i ++) {
		printf ("%d ", dis[i]);
	}
	
	return 0;
}

最小生成树

Kruskal

#include <bits/stdc++.h>

using namespace std;

#define N 5001
#define M 200001
struct node {
	int u, v, w;
}edge[M];
int fa[N], n, m;

int find (int x) {//并查集找爸爸 
	return fa[x] == x ? x : fa[x] = find (fa[x]);
} 

void un (int x, int y) {//并查集连接 
	x = find (x);
	y = find (y);
	fa[x] = y;
}

void ini () {//初始化 
	for (int i = 1; i <= 5000; i ++) fa[i] = i;
}

bool cmp (node a, node b) {
	return a.w < b.w;
}

int main () {
	
	ini ();
	scanf ("%d %d", &n, &m);
	for (int i = 1; i <= m; i ++) {
		scanf ("%d %d %d", &edge[i].u, &edge[i].v, &edge[i].w);
	}
	sort (edge + 1, edge + m + 1, cmp);
	int k = 0;
	int ans = 0;
	for (int i = 1; i <= m; i ++) {
		if (find (edge[i].u) != find (edge[i].v)){//判断是否在一个集合里 
			un (edge[i].u,edge[i].v);
			k ++;
			ans += edge[i].w;//累加答案 
		}
		if(k == n - 1) break;
	}
	if (k == n - 1) printf ("%d", ans);
	else printf ("orz");//不连通 
		
    return 0;
}

排序

归并排序(求逆序对)

#include<bits/stdc++.h>

using namespace std;

int n;
int ans = 0;
int v[500001];
int t[500001];

void Qsort (int l, int r) {//归并 
	if(l == r)return ;
	int mid = (l + r) >> 1;
	Qsort (1, mid);
	Qsort (mid + 1, r);//递归 
	int i = l; int j = mid + 1; int k = l;
	while (i <= mid && j <= r) {
		if (v[i] <= v[j]) t[k ++] = v[i ++];
		else t[k ++] = v[j ++], ans += mid - i + 1;//数学规律 
	}
	while (i <= mid) t[k ++] = v[i ++];
	while (j <= r) t[k ++] = v[j ++];
	for (int i = l; i <= r; i ++) v[i] = t[i];
}

int main () {
	
	scanf ("%d", &n);
	for(int i = 1; i <= n; i ++) scanf ("%d", &v[i]);
	Qsort (1, n);
	printf ("%d", ans);
	
	return 0;
}

数据结构

树状数组(区间查询,区间修改)

#include<bits/stdc++.h>

using namespace std;

int a[500001], b[500001], c[500001];
int n, m;

int lowbit (int x) {
	return x & (-x);
}

void updata (int i, int k) {
	int x = i;
	while (i <= n) {
		c[i] += k;
		b[i] += k * (x - 1);
		i += lowbit (i);
	}
}

int getsum (int i) {
	int sum = 0, x = i;
	while (i > 0) {
		sum += x * c[i] - b[i];
		i -= lowbit (i);
	}
	return sum;
}

//1:区间修改,2:区间查询 
int main () {
	
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; i ++) {
		scanf ("%d", &a[i]);
		updata (i, a[i] - a[i-1]);
	}
	for (int i = 1, d, x, y, z; i <= m; i ++) {
		scanf ("%d", &d);
		if (d == 1) {
			scanf ("%d%d%d", &x, &y, &z);
			updata (x, z);
			updata (y+1, -z);
		} else {
			scanf ("%d%d", &x, &y);
			printf ("%d
", getsum (y) - getsum (x - 1));
		}
	}
	
	return 0;
}

链表(尾部插入,遍历)

struct node {
    int data;
    node *next;
};

struct list {
    node *head;
    int length;
};

void add (list &List, int n) {
    node *pcur = new node;
    pcur -> data = n;
    pcur -> next = NULL;
    if (List.head == NULL) {
        List.head = pcur;
        List.length = 1;
    } else {
        node *pt = List.head;
        while (pt -> next != NULL) pt = pt -> next;
        pt -> next = pcur;
        List.length ++;
    }
}

int main () {

    list L;
    L.head = NULL;
    L.length = 0;
    int n;
    cin >> n;
    for (int i = 1; i <= n; i ++) {
        int du;
        cin >> du;
        add (L, du);
    }
    node *bl;
    bl = L.head;
    while (bl != NULL) {
        cout << bl -> data << " ";
        bl = bl -> next;
    }

    return 0;
}

链表 (数组模拟,头尾插,随机插)

#include <bits/stdc++.h>
#define LL long long

using namespace std;

struct FastIO {
	template <typename T> FastIO& operator >> (T& In) {
		In = 0;
		char Ch = getchar ();
		int Flag = 1;
		for (; ! std :: isdigit (Ch); Ch = getchar ()) if (Ch == '-') Flag = -1;
		for (;   std :: isdigit (Ch); Ch = getchar ()) In = (In << 3) + (In << 1) + (Ch ^ 48);
		In *= Flag;
		return *this;
	}
}fin;

const int MaxN = 2010;
int Val[MaxN], Nxt[MaxN];
int Head, Size;

void AddHead (int x) {
	Val[Size] = x;
	Nxt[Size] = Head;
	Head = Size;
	Size ++;
}

void Init () {
	Head = -1;
	Size = 0;
	AddHead (0);
}

void AddTail (int x) {
	Val[Size] = x; 
	Nxt[Size] = Nxt[Size - 1];
	Nxt[Size - 1] = Size;
	Size ++;
}

void AddRy (int k, int x) {
	Val[Size] = x;
	Nxt[Size] = Nxt[k];
	Nxt[k] = Size;
	Size ++;
}

void Delete (int k) {
	Nxt[k] = Nxt[Nxt[k]];
}

void Write () {
	int i = Nxt[Head];
	for (; i != -1; i = Nxt[i]) printf ("%d ", Val[i]);
}

int main () {
	
	Init ();
    int n;
    fin >> n;
    for (int i = 1; i <= n; i ++) {
    	int x;
    	fin >> x;
    	AddTail (x);
	}
	int m;
	fin >> m;
	for (int i = 1; i <= m; i ++) {
		int k, x;
		fin >> k >> x;
		AddRy (k, x);
	}
	Write ();
    
    return 0; 
}

线段树 (区间修改,区间查询)

#include <bits/stdc++.h>
#define ls (root << 1)
#define rs (root << 1 | 1)
#define int long long

using namespace std;

struct FastIO {
	template <typename T> FastIO& operator >> (T& in) {
		in = 0;
		char ch = getchar ();
		int flag = 1;
		for (; ! isdigit (ch); ch = getchar ()) if (ch == '-') flag = -1;
		for (;   isdigit (ch); ch = getchar ()) in = (in << 3) + (in << 1) + (ch ^ 48);
		in *= flag;
		return *this;
	}
}fin;

const int MaxN = 1e5 + 100;
int sum[MaxN << 2], l[MaxN << 2], r[MaxN << 2], lz[MaxN << 2], arr[MaxN];
int n, m;

void pushup (int root) {
	sum[root] = sum[ls] + sum[rs];
}

void pushdown (int root) {
	if (lz[root]) {
		lz[ls] += lz[root];
		lz[rs] += lz[root];
		sum[ls] += lz[root] * (r[ls] - l[ls] + 1);
		sum[rs] += lz[root] * (r[rs] - l[rs] + 1);
		lz[root] = 0;
	}
}

void build (int root, int L, int R) {
	l[root] = L;
	r[root] = R;
	lz[root] = 0;
	if (L == R) {
		sum[root] = arr[L];
		return ;
	}
	int mid = (L + R) >> 1;
	build (ls, L, mid);
	build (rs, mid + 1, R);
	pushup (root);
}

void add (int root, int L, int R, int k) {
	if (l[root] >= L && r[root] <= R) {
		sum[root] += (r[root] - l[root] + 1) * k;
		lz[root] += k;
		return ;
	}
	if (r[root] < L || l[root] > R) return ;
	pushdown (root);
	if (r[ls] >= L) add (ls, L, R, k);
	if (l[rs] <= R) add (rs, L, R, k);
	pushup (root);
}

int search (int root, int L, int R) {
	if (l[root] >= L && r[root] <= R) return sum[root];
	if (r[root] < L || l[root] > R) return 0;
	pushdown (root);
	int s = 0;
	if (r[ls] >= L) s += search (ls, L, R);
	if (l[rs] <= R) s += search (rs, L, R);
	return s;
}

main () {
	
	fin >> n >> m;
	for (int i = 1; i <= n; ++ i) fin >> arr[i];
	build (1, 1, n);
	for (int i = 1; i <= m; ++ i) {
		int id;
		fin >> id;
		if (id == 1) {
			int x, y, z;
			fin >> x >> y >> z;
			add (1, x, y, z);
		} else {
			int x, y;
			fin >> x >> y;
			printf ("%lld
", search (1, x, y));
		}
	}
	
	return 0;
}

Treap

#include <bits/stdc++.h>
#define Reg register
#define RI Reg int
#define RL Reg LL
#define RU Reg ull
#define Con const
#define CI Con int&
#define CL Con LL&
#define CU Con ull&
#define I inline
#define W while
#define LL long long
#define ull unsigned long long

using namespace std;

struct FastIO {
	template <typename T> FastIO& operator >> (T& in) {
		in = 0;
		char ch = getchar ();
		int flag = 1;
		for (; ! std :: isdigit (ch); ch = getchar ()) if (ch == '-') flag = -1;
		for (;   std :: isdigit (ch); ch = getchar ()) in = (in << 3) + (in << 1) + (ch ^ 48);
		in *= flag;
		return *this;
	}
}fin;

const int MaxN = 1e6 + 100, INF = 1e9;
int tot = 0, root = 0;
struct NODE {
	int val;
	int dat;
	int size;
	int cnt;
	int ch[2];
}nd[MaxN];

int NewNode (int x) { // 创建新节点 
	++ tot;
	nd[tot].val = x;
	nd[tot].dat = rand ();
	nd[tot].cnt = 1;
	nd[tot].size = 1;
	nd[tot].ch[0] = 0;
	nd[tot].ch[1] = 0;
	return tot;
}

void PushUp (int x) { // 更新 
	nd[x].size = nd[nd[x].ch[0]].size + nd[nd[x].ch[1]].size + nd[x].cnt;
}

void Build () { // 初始化 
	root = NewNode (-INF);
	nd[root].ch[1] = NewNode (INF);
	PushUp (root);
}

void Rotate (int &id, int d) { // 旋转     0:左旋      1:右旋 
	int Tmp = nd[id].ch[d ^ 1];
	nd[id].ch[d ^ 1] = nd[Tmp].ch[d];
	nd[Tmp].ch[d] = id;
	id = Tmp;
	PushUp (nd[id].ch[d]);
	PushUp (id);
}

void Insert (int &id, int x) { // 插入 
	if (! id) {
		id = NewNode (x);
		return ;
	}
	if (x == nd[id].val) ++ nd[id].cnt;
	else {
		int d = x < nd[id].val ? 0 : 1;
		Insert (nd[id].ch[d], x);
		if (nd[id].dat < nd[nd[id].ch[d]].dat) Rotate (id, d ^ 1);
	}
	PushUp (id);
}

void Remove (int &id, int x) { // 删除 
	if (! id) return ;
	if (x == nd[id].val) {
		if (nd[id].cnt > 1) {-- nd[id].cnt; PushUp (id); return ;}
		if (nd[id].ch[0] || nd[id].ch[1]) {
			if (! nd[id].ch[1] || nd[nd[id].ch[0]].dat > nd[nd[id].ch[1]].dat) {
				Rotate (id, 1);
				Remove (nd[id].ch[1], x);
			} else {
				Rotate (id, 0);
				Remove (nd[id].ch[0], x);
			}
			PushUp (id);
		} else id = 0;
		return ;
	}
	if (x < nd[id].val) Remove (nd[id].ch[0], x);
	else Remove (nd[id].ch[1], x);
	PushUp (id);
}

int Rank (int id, int x) { // 查找x的排名 
	if (! id) return -2;
	if (x == nd[id].val) return nd[nd[id].ch[0]].size + 1;
	else if (x < nd[id].val) return Rank (nd[id].ch[0], x);
	else return nd[nd[id].ch[0]].size + nd[id].cnt + Rank (nd[id].ch[1], x);
}

int Val (int id, int rank) { // 查找排名为rank的数 
	if (! id) return INF;
	if (rank <= nd[nd[id].ch[0]].size) return Val (nd[id].ch[0], rank);
	else if (rank <= nd[nd[id].ch[0]].size + nd[id].cnt) return nd[id].val;
	else return Val (nd[id].ch[1], rank - nd[nd[id].ch[0]].size - nd[id].cnt);
}

int Pre (int x) { // 查找x的前驱 
	int id = root, pre;
	while (id) {
		if (nd[id].val < x) pre = nd[id].val, id = nd[id].ch[1];
		else id = nd[id].ch[0];
	}
	return pre;
}

int Next (int x) { // 查找x的后继 
	int id = root, next;
	while (id) {
		if (nd[id].val > x) next = nd[id].val, id = nd[id].ch[0];
		else id = nd[id].ch[1];
	}
	return next;
}

int n;
int opt, x;
//1:插入	2:删除	3:查找x的排名	4:查找排名为rank的数	5:查找x的前驱	6:查找x的后继 
int main () {

	Build ();
	fin >> n;
	for (int i = 1; i <= n; ++ i) {
		fin >> opt >> x;
		if (opt == 1) Insert (root, x);
		else if (opt == 2) Remove (root, x);
		else if (opt == 3) printf ("%d
", Rank (root, x) - 1);
		else if (opt == 4) printf ("%d
", Val (root, x + 1));
		else if (opt == 5) printf ("%d
", Pre (x));
		else if (opt == 6) printf ("%d
", Next (x));
	}
	
    return 0;
}   

fhq_treap

#include <bits/stdc++.h>

using namespace std;

struct FastIO {
	template <typename T> FastIO& operator >> (T& in) {
		in = 0;
		char ch = getchar ();
		int flag = 1;
		for (; ! isdigit (ch); ch = getchar ()) if (ch == '-') flag = -1;
		for (;   isdigit (ch); ch = getchar ()) in = (in * 10) + (ch ^ 48);
		in *= flag;
		return *this;
	}
}fin;

const int MaxN = 5e5 + 100;
int ch[MaxN][2], val[MaxN], rnd[MaxN], size[MaxN], cnt = 0;
int x, y, z, root = 0;
int n;

void pushup (int root) {size[root] = size[ch[root][0]] + size[ch[root][1]] + 1;}
int newnode (int v) {
	++ cnt;
	size[cnt] = 1;
	val[cnt] = v;
	ch[cnt][0] = ch[cnt][1] = 0;
	rnd[cnt] = rand ();
	return cnt;
}

void split (int now, int k, int &x, int &y) {
	if (! now) x = y = 0;
	else {
		if (val[now] <= k) x = now, split (ch[now][1], k, ch[now][1], y);
		else y = now, split (ch[now][0], k, x, ch[now][0]);
		pushup (now);
	}
}

int merge (int A, int B) {
	if (! A || ! B) return A + B;
	if (rnd[A] < rnd[B]) {ch[A][1] = merge (ch[A][1], B); pushup (A); return A;}
	else {ch[B][0] = merge (A, ch[B][0]); pushup (B); return B;}
}

void Insert (int &now, int v) {
	split (now, v, x, y);
	now = merge (merge (x, newnode (v)), y);
}

void Del (int &now, int v) {
	split (now, v, x, z);
	split (x, v - 1, x, y);
	y = merge (ch[y][0], ch[y][1]);
	now = merge (merge (x, y), z);
}

int Rank (int &now, int v) {
	split (now, v - 1, x, y);
	int res = size[x] + 1;
	now = merge (x, y);
	return res;
}

int Val (int now, int rank) {
	while (1) {
		if (rank <= size[ch[now][0]]) now = ch[now][0];
		else if (rank == size[ch[now][0]] + 1) return val[now];
		else rank -= size[ch[now][0]] + 1, now = ch[now][1];
	}
}

int Pre (int &now, int v) {
	split (now, v - 1, x, y);
	int res = Val (x, size[x]);
	now = merge (x, y);
	return res;
}

int Next (int &now, int v) {
	split (now, v, x, y);
	int res = Val (y, 1);
	now = merge (x, y);
	return res;
}

int main () {
	
	srand (time (0));
	fin >> n;
	for (int i = 1; i <= n; ++ i) {
		int opt, v;
		fin >> opt >> v;
		switch (opt) {
			case 1: Insert (root, v); break;
			case 2: Del (root, v); break;
			case 3: printf ("%d
", Rank (root, v)); break;
			case 4: printf ("%d
", Val (root, v)); break;
			case 5: printf ("%d
", Pre (root, v)); break;
			case 6: printf ("%d
", Next (root, v)); break;
		}
	}
	
	return 0;
}

子序列

LCS(最长公共子序列)

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#define N 100001
int dp[2][N], a[N], b[N];
int n; 
int main(){
	
	scanf ("%d", &n);
	for (int i = 1; i <= n; i ++){
		scanf ("%d", &a[i]);
	}
	for (int i = 1; i <= n; i ++){
		scanf ("%d", &b[i]);
	}
	for (int i = 1; i <= n; i ++){
		for (int j = 1; j <= n; j ++){
			if (a[i] != b[j]){
				dp[i & 1][j] = max (dp[1 - i & 1][j], dp[i & 1][j - 1]);//状态转移方程式 
			}else{
				dp[i & 1][j] = dp[1 - i & 1][j - 1] + 1;
			}
		}
	}
	printf ("%d", dp[n & 1][n]);//滚动数组 
	
	return 0;
}

LIS(最长上升子序列)

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int a[100001], d[100001], n, len;
int main (){
	
    scanf ("%d", &n);
    for(int i = 1; i <= n; i ++){
        scanf ("%d", &a[i]);
    }
    d[1] = a[1];
    len = 1;
    for(int i = 2; i <= n; i ++){
        if (a[i] > d[len]) d[++ len] = a[i];
        else{
            int j = upper_bound (d + 1, d + len + 1, a[i]) - d;
            d[j] = a[i];
        }
    }
    printf ("%d", len);
    
    return 0;
}

LCA

倍增

#include <bits/stdc++.h>
#define DEBUG 0

using namespace std;

struct FastIO {
	template <typename T> FastIO& operator >> (T& in) {
		in = 0;
		char ch = getchar ();
		int flag = 1;
		for (; ! isdigit (ch); ch = getchar ()) if (ch == '-') flag = -1;
		for (;   isdigit (ch); ch = getchar ()) in = (in << 3) + (in << 1) + (ch ^ 48);
		in *= flag;
		return *this;
	}
}fin;

const int MaxN = 5e5 + 100;
int n, m, s;
int head[MaxN], to[MaxN << 1], nxt[MaxN << 1], cnt;
int lg[MaxN], dep[MaxN], fa[MaxN][25];
void add (int u, int v) {++ cnt; to[cnt] = v; nxt[cnt] = head[u]; head[u] = cnt;}

void dfs (int now, int fath) {
	fa[now][0] = fath; dep[now] = dep[fath] + 1;
	for (int i = 1; i <= lg[dep[now]]; ++ i) fa[now][i] = fa[fa[now][i - 1]][i - 1];
	for (int i = head[now]; i; i = nxt[i]) {
		if (to[i] != fath) dfs (to[i], now);
	}
}

int LCA (int x, int y) {
	if (dep[x] < dep[y]) swap (x, y);
	while (dep[x] > dep[y]) x = fa[x][lg[dep[x] - dep[y]] - 1];
	if (x == y) return x;
	for (int i = lg[dep[x]] - 1; i >= 0; -- i) {
		if (fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i];
	}
	return fa[x][0];
}

int main () {
    
    fin >> n >> m >> s;
	for (int i = 1; i <= n - 1; ++ i) {
		int x, y;
		fin >> x >> y;
		add (x, y); add (y ,x);
	}
	for (int i = 1; i <= n; ++ i) lg[i] = lg[i - 1] + (1 << lg[i - 1] == i);
	dfs (s, 0);
	for (int i = 1; i <= m; ++ i) {
		int x, y;
		fin >> x >> y;
		printf ("%d
", LCA (x, y));
	}

    return 0;
}
原文地址:https://www.cnblogs.com/binghun/p/sf.html