最短路
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;
}