模板集合

一.基础算法

贪心

二分

整数域上的二分

分治

倍增

搜索

离散化

离散化区间

二.字符串基础

 

三.dp(没有固定模板,但以下的主干部分基本相同)

区间dp

数位dp

单调队列优化dp

 

四.图论

拓扑排序

 

欧拉回路

 

最小生成树(kruskal/prim)

P3366 【模板】最小生成树

kruskal

 1 //09/09/19 14:25 kruskal复习 
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <algorithm>
 6 #define ll long long
 7 using namespace std;
 8 
 9 template <typename T> void in(T &x) {
10     x = 0; T f = 1; char ch = getchar();
11     while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
12     while(isdigit(ch)) {x = 10*x+ch-'0'; ch = getchar();}
13     x *= f;
14 }
15 
16 template <typename T> void out(T x) {
17     if(x < 0) putchar('-'),x = -x;
18     if(x > 9) out(x/10);
19     putchar(x%10+'0');
20 }
21 //---------------------------------------------------------------
22 
23 const int N = 5005,M = 200005;
24 
25 int n,m,s,ans;
26 int fa[N];
27 
28 struct edge {
29     int u,v,w;
30     bool operator < (const edge &sed) const {
31         return w < sed.w;
32     }
33 }e[M];
34 
35 int find(int x) {
36     return fa[x] == x ? x : fa[x] = find(fa[x]);
37 }
38 
39 int main() {
40     int i; in(n); in(m);
41     for(i = 1;i <= m; ++i) {
42         in(e[i].u); in(e[i].v); in(e[i].w);
43     }
44     sort(e+1,e+m+1);
45     for(i = 1;i <= n; ++i) fa[i] = i;
46     int cnt = 0;
47     for(i = 1;i <= m; ++i) {
48         int x = find(e[i].u),y = find(e[i].v);
49         if(x == y) continue;
50         ++cnt; fa[x] = y; ans += e[i].w;
51         if(cnt == n-1) break;
52     }
53     if(cnt == n-1) out(ans);
54     else printf("orz");
55     return 0;
56 }
kruskal

prim

 1 //09/09/19 14:25 kruskal复习 
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <algorithm>
 6 #include <queue>
 7 #define ll long long
 8 using namespace std;
 9 
10 template <typename T> void in(T &x) {
11     x = 0; T f = 1; char ch = getchar();
12     while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
13     while(isdigit(ch)) {x = 10*x+ch-'0'; ch = getchar();}
14     x *= f;
15 }
16 
17 template <typename T> void out(T x) {
18     if(x < 0) putchar('-'),x = -x;
19     if(x > 9) out(x/10);
20     putchar(x%10+'0');
21 }
22 //---------------------------------------------------------------
23 
24 const int N = 5005,M = 200005;
25 
26 int n,m,ans;
27 int dis[N],vis[N];
28 
29 struct edge {
30     int v,w,nxt;
31     edge(int v = 0,int w = 0,int nxt = 0):v(v),w(w),nxt(nxt){};
32 }e[M<<1]; int head[N],e_cnt;
33 
34 void add(int u,int v,int w) {
35     e[++e_cnt] = edge(v,w,head[u]); head[u] = e_cnt;
36 }
37 
38 struct node {
39     int pos,dis;
40     node(int pos = 0,int dis = 0):pos(pos),dis(dis){};
41     bool operator < (const node &sed) const {
42         return dis > sed.dis;//debug 优先队列默认是大根堆
43     }
44 };
45 
46 priority_queue <node> q;
47 
48 void prim() {//贪点 
49     memset(dis,0x3f,sizeof(dis));
50     q.push(node(1,0)); dis[1] = 0; int cnt = 0;//debug 此处cnt为已加入树中的点数(不同于kruskal的贪边) 
51     while(!q.empty()) {
52         node _u = q.top(); q.pop();
53         int u = _u.pos;
54         if(vis[u]) continue; vis[u] = 1;
55         ++cnt; ans += _u.dis;
56         if(cnt == n) break;//注意 
57         for(int i = head[u]; i;i = e[i].nxt) {
58             int v = e[i].v;
59             if(dis[v] > e[i].w) {
60                 dis[v] = e[i].w; q.push(node(v,dis[v]));
61             }
62         }
63     }
64     if(cnt == n) out(ans);
65     else printf("orz");
66 }//prim 的写法与dijkstra如出一辙 主要区别在于dijkstra的dis代表到源点的最短距离,而prim的dis代表未加入树集的点到树集(连通块)的最小距离 
67 //本质上都是贪心
68 
69 int main() {
70     int i,u,v,w; in(n); in(m);
71     for(i = 1;i <= m; ++i) {
72         in(u); in(v); in(w); 
73         add(u,v,w); add(v,u,w);
74     }
75     prim();
76     return 0;
77 }
prim

 

最短路(spfa/dijkstra/floyd)

spfa(slf优化)

P3371 【模板】单源最短路径(弱化版)

 1 //09/09/19 15:21 spfa(slf优化)复习 
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <algorithm>
 6 #include <queue>
 7 #define ll long long
 8 using namespace std;
 9 
10 template <typename T> void in(T &x) {
11     x = 0; T f = 1; char ch = getchar();
12     while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
13     while(isdigit(ch)) {x = 10*x+ch-'0'; ch = getchar();}
14     x *= f;
15 }
16 
17 template <typename T> void out(T x) {
18     if(x < 0) putchar('-'),x = -x;
19     if(x > 9) out(x/10);
20     putchar(x%10+'0');
21 }
22 //---------------------------------------------------------------
23 
24 const int N = 10007,M = 500007;
25 
26 int n,m,s;
27 
28 struct edge {
29     int v,w,nxt;
30     edge(int v = 0,int w = 0,int nxt = 0):v(v),w(w),nxt(nxt){};
31 }e[M]; int head[N],e_cnt;
32 
33 void add(int u,int v,int w) {
34     e[++e_cnt] = edge(v,w,head[u]); head[u] = e_cnt;
35 }
36 
37 int dis[N],inque[N];
38 deque <int> q;
39 
40 void spfa() {
41     memset(dis,0x3f,sizeof(dis));
42     q.push_back(s); dis[s] = 0; inque[s] = 1;
43     while(!q.empty()) {
44         int u = q.front(); q.pop_front(); inque[u] = 0;//易错未写 inque[u] = 0 
45         for(int i = head[u]; i;i = e[i].nxt) {
46             int v = e[i].v;
47             if(dis[v] > dis[u]+e[i].w) {
48                 dis[v] = dis[u]+e[i].w;
49                 if(!inque[v]) {
50                     if(!q.empty() && dis[v] < dis[q.front()]) q.push_front(v);//易错未写 q.empty
51                     else q.push_back(v);
52                     inque[v] = 1;
53                 }
54             }
55         }
56     }
57     for(int i = 1;i <= n; ++i) {
58         if(dis[i] != 0x3f3f3f3f) out(dis[i]);
59         else out((1<<31)-1);
60         putchar(' ');
61     }
62 }
63 
64 int main() {
65     int i,u,v,w; in(n); in(m); in(s);
66     for(i = 1; i <= m; ++i) {
67         in(u); in(v); in(w); add(u,v,w);
68     }
69     spfa();
70     return 0;
71 }
spfa(slf优化)

dijkstra(堆优化)

P4779 【模板】单源最短路径(标准版)

 1 //09/09/19 15:39 dijkstra(堆优化)复习 
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <algorithm>
 6 #include <queue>
 7 #define ll long long
 8 using namespace std;
 9 
10 template <typename T> void in(T &x) {
11     x = 0; T f = 1; char ch = getchar();
12     while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
13     while(isdigit(ch)) {x = 10*x+ch-'0'; ch = getchar();}
14     x *= f;
15 }
16 
17 template <typename T> void out(T x) {
18     if(x < 0) putchar('-'),x = -x;
19     if(x > 9) out(x/10);
20     putchar(x%10+'0');
21 }
22 //---------------------------------------------------------------
23 
24 const int N = 100007,M = 200007;
25 
26 int n,m,s;
27 
28 struct edge {
29     int v,w,nxt;
30     edge(int v = 0,int w = 0,int nxt = 0):v(v),w(w),nxt(nxt){};
31 }e[M]; int head[N],e_cnt;
32 
33 void add(int u,int v,int w) {
34     e[++e_cnt] = edge(v,w,head[u]); head[u] = e_cnt;
35 }
36 
37 ll dis[N];
38 bool vis[N];
39 
40 struct node {
41     int pos; ll dis;
42     node(int pos = 0,ll dis = 0):pos(pos),dis(dis){};
43     bool operator < (const node &sed) const {
44         return dis > sed.dis;//debug 又写反了 
45     }
46 };
47 
48 priority_queue <node> q;
49 
50 void dijkstra() {
51     memset(dis,0x7f,sizeof(dis));
52     q.push(node(s,0)); dis[s] = 0; //vis[s] = 1;
53     while(!q.empty()) {
54         node _u = q.top(); q.pop();
55         int u = _u.pos;
56         if(vis[u]) continue; vis[u] = 1;
57         for(int i = head[u]; i;i = e[i].nxt) {
58             int v = e[i].v; 
59             if(dis[v] > dis[u]+e[i].w) {
60                 dis[v] = dis[u]+e[i].w;
61                 //if(vis[v]) continue;
62                 q.push(node(v,dis[v]));
63                 //vis[v] = 1;
64             }
65         }
66     }
67     for(int i = 1;i <= n; ++i) out(dis[i]),putchar(' ');
68 }
69 
70 int main() {
71     int i,u,v,w; in(n); in(m); in(s);
72     for(i = 1; i <= m; ++i) {
73         in(u); in(v); in(w); add(u,v,w);
74     }
75     dijkstra();
76     return 0;
77 }
dijkstra(堆优化)

*有向图中,单汇最短可以通过建反图的方式转化为单源最短(P1629,P1342)

floyd

多源最短路

传递闭包

求最小环(输出方案)

 

差分约束系统

(强连通分量)缩点

割点/桥

点/边双连通分量

 

二分图

二分图最大匹配

二分图完美匹配

二分图带权匹配

 

*网络流

最大流

最小费用流

 

五.数据结构(数据处理)

前缀和

RMQ

差分/二维差分

树状数组

线段树

平衡树(splay)

 

六.树

树的前/中/后序遍历

树的直径

树的重心

lca(倍增求lca/树链剖分求lca)

树上差分(边差分/点差分)

树链剖分

  1 //09/09/19 08:55 树剖复习 
  2 #include <iostream>
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <algorithm>
  6 #define ll long long
  7 using namespace std;
  8 
  9 template <typename T> void in(T &x) {
 10     x = 0; T f = 1; char ch = getchar();
 11     while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
 12     while(isdigit(ch)) {x = 10*x+ch-'0'; ch = getchar();}
 13     x *= f;
 14 }
 15 
 16 template <typename T> void out(T x) {
 17     if(x < 0) putchar('-'),x = -x;
 18     if(x > 9) out(x/10);
 19     putchar(x%10+'0');
 20 }
 21 //---------------------------------------------------------------
 22 
 23 const int N = 1e5+7;
 24 
 25 int n,m,r,p,a[N]; 
 26 
 27 struct edge {
 28     int v,nxt;
 29     edge(int v = 0,int nxt = 0):v(v),nxt(nxt){};
 30 }e[N<<1]; int head[N],e_cnt;
 31 
 32 void add(int u,int v) {
 33     e[++e_cnt] = edge(v,head[u]); head[u] = e_cnt;
 34 }
 35 //---------------------------------------------------------------
 36 //init
 37 //pre_dfs1
 38 int fa[N],dep[N],sz[N],son[N];
 39 void dfs1(int u) {
 40     dep[u] = dep[fa[u]]+1; sz[u] = 1; int maxs = 0;
 41     for(int i = head[u]; i;i = e[i].nxt) {
 42         int v = e[i].v; if(v == fa[u]) continue; 
 43         fa[v] = u; dfs1(v); sz[u] += sz[v];//debug not wt sz[u] += sz[v]
 44         if(sz[v] > maxs) maxs = sz[v],son[u] = v;
 45     }
 46 }
 47 //pre_dfs2
 48 int top[N],id[N],w[N],cnt;
 49 void dfs2(int u,int ctop) {
 50     top[u] = ctop; id[u] = ++cnt; w[id[u]] = a[u];
 51     if(son[u]) dfs2(son[u],ctop);
 52     for(int i = head[u]; i;i = e[i].nxt) {
 53         int v = e[i].v; if(v == fa[u] || v == son[u]) continue; dfs2(v,v);
 54     }
 55 }
 56 //---------------------------------------------------------------
 57 //segment tree
 58 ll sum[N<<2],lazy[N<<2];
 59 
 60 void P_dn(int u,int l,int r) {
 61     if(!lazy[u]) return;
 62     int mid = (l+r)>>1;
 63     sum[u<<1] = (sum[u<<1]+(lazy[u]*(mid-l+1))%p)%p; lazy[u<<1] = (lazy[u<<1]+lazy[u])%p;
 64     sum[u<<1|1] = (sum[u<<1|1]+(lazy[u]*(r-mid))%p)%p; lazy[u<<1|1] = (lazy[u<<1|1]+lazy[u])%p;
 65     lazy[u] = 0;
 66 }
 67 
 68 void Build(int u,int l,int r) {
 69     if(l == r) {sum[u] = w[l]; return;}
 70     int mid = (l+r)>>1;
 71     Build(u<<1,l,mid); Build(u<<1|1,mid+1,r);
 72     sum[u] = (sum[u<<1]+sum[u<<1|1])%p;
 73 }
 74 
 75 void A(int u,int l,int r,int x,int y,ll k) {
 76     if(x <= l && y >= r) {sum[u] = (sum[u]+(k*(r-l+1))%p)%p; lazy[u] = (lazy[u]+k)%p; return;}
 77     P_dn(u,l,r); int mid = (l+r)>>1;
 78     if(x <= mid) A(u<<1,l,mid,x,y,k); if(y > mid) A(u<<1|1,mid+1,r,x,y,k);
 79     sum[u] = (sum[u<<1]+sum[u<<1|1])%p;
 80 }
 81 
 82 ll Q(int u,int l,int r,int x,int y) {
 83     if(x <= l && y >= r) return sum[u];
 84     P_dn(u,l,r); int mid = (l+r)>>1; ll res = 0;//debug 线段树基础不扎实,返回值应用long long 
 85     if(x <= mid) res = (res+Q(u<<1,l,mid,x,y))%p; if(y > mid) res = (res+Q(u<<1|1,mid+1,r,x,y))%p;//debug 第二个忘记%p 30pts -> 100pts 
 86     return res;
 87 }
 88 //---------------------------------------------------------------
 89 //chain
 90 
 91 void modify(int x,int y,int z) {
 92     while(top[x] != top[y]) {//不在一条重链上 
 93         if(dep[top[x]] < dep[top[y]]) swap(x,y);//每次让深的跳 
 94         //A(1,1,n,top[x],x,z); x = top[x];//WA
 95         A(1,1,n,id[top[x]],id[x],z); 
 96         x = fa[top[x]];//易错1不加id //易错2 不写 x = fa[top[x]] //易错3不加fa 
 97     }
 98     if(dep[x] < dep[y]) swap(x,y);
 99     A(1,1,n,id[y],id[x],z);
100 }
101 
102 ll query(int x,int y) {
103     ll res = 0;
104     while(top[x] != top[y]) {
105         if(dep[top[x]] < dep[top[y]]) swap(x,y);
106         res = (res+Q(1,1,n,id[top[x]],id[x]))%p; 
107         x = fa[top[x]];
108     }
109     if(dep[x] < dep[y]) swap(x,y);
110     return res = (res+Q(1,1,n,id[y],id[x]))%p;
111 }
112 
113 
114 int main() {
115 //    freopen("0.in","r",stdin);
116     int i,x,y,z,op; in(n); in(m); in(r); in(p);
117     for(i = 1;i <= n; ++i) in(a[i]);
118     for(i = 1;i < n; ++i) {
119         in(x); in(y); add(x,y); add(y,x);
120     }
121     dfs1(r); dfs2(r,r); Build(1,1,n);
122     while(m--) {
123         in(op); in(x);
124         if(op == 1) {
125             in(y); in(z); modify(x,y,z%p);
126         }//1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z
127         else if(op == 2) {
128             in(y); out(query(x,y)),putchar('\n');
129         }//2 x y 表示求树从x到y结点最短路径上所有节点的值之和
130         else if(op == 3) {
131             in(z); A(1,1,n,id[x],id[x]+sz[x]-1,z%p);
132         }//3 x z 表示将以x为根节点的子树内所有节点值都加上z
133         else {
134             out(Q(1,1,n,id[x],id[x]+sz[x]-1)); putchar('\n');
135         }//4 x 表示求以x为根节点的子树内所有节点值之和
136     }
137     return 0;
138 }
树剖模板 

*点分治

七.数学基础

gcd/lcm 

线性筛

快速幂

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <cmath>
 6 #include <queue>
 7 #include <vector>
 8 #define ll long long
 9 using namespace std;
10 
11 template <typename T> void in(T &x) {
12     x = 0; T f = 1; char ch = getchar();
13     while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
14     while(isdigit(ch)) {x = 10*x+ch-'0'; ch = getchar();}
15     x *= f;
16 }
17 
18 template <typename T> void out(T x) {
19     if(x < 0) putchar('-'),x = -x;
20     if(x > 9) out(x/10);
21     putchar(x%10+'0');
22 }
23 //---------------------------------------------------------------
24 
25 ll b,p,k;
26 
27 ll power(ll a,ll b,ll p) {
28     ll res = 1%p;//debug 1^0 mod 1 = 0//注意%p
29     for(;b;b >>= 1) {
30         if(b&1) res = (res*a)%p;
31         a = (a*a)%p;
32     }
33     return res;
34 }
35 
36 int main() {
37     in(b); in(p); in(k);
38     printf("%lld^%lld mod %lld=%lld",b,p,k,power(b,p,k));
39     return 0;
40 }
快速幂

 

八.STL

九.骗分

随机化

random_shuffle

模拟退火

posted @ 2019-09-09 08:37  陈星卿  阅读(159)  评论(0编辑  收藏  举报