【模板】板子合集~(填坑中)

一些要背的模板~(填坑中)

  • 完成


注意事项

  • 完成

注意事项



搜索

  • 完成

DFS(深搜)

Depth First Search

  • 完成
#include<bits/stdc++.h>
using namespace std;
	
int n, vis[12], num[12];

void dfs(int cnt){
	if(cnt == n){
	    //TODO
		return;
	}
	for(int i=1;i<=n;i++)
	{
        if(!vis[i])
        {
		    num[cnt+1]=i;
            vis[i]=1;
            dfs(cnt+1);
            vis[i]=0;
        }
	}
}

int main(){
	cin >> n;
	dfs(0);
	return 0;
}

BFS(宽搜)

Breath First Search

  • 完成
void bfs(s){
  queue<int> q;
  q.push(s);
  visited[s] = 1;
  while (!q.empty()){
    u = q.top();
    q.pop();
    for (与s相连的点v){
      if (!visited[v]){
        q.push(v);
        visited[v] = 1;
      }
    }
  }
}

中间相遇

  • 完成
 


图论

  • 完成

储存

  • 完成
1.邻接数组(邻接矩阵)
  • 完成
 #include<bits/stdc++.h>
using namespace std;
const int INF = 1 << 30;

int graph[105][105];

int main(){
	int n, m;//点数,边数
	int a, b, c;//起点,重点,边权
	cin >> n >> m;
	
	for(int i=1;i<=n;i++)//初始化
		for(int j=1;j<=n;j++)
			if(i == j)
				graph[i][j] = 0;
			else
				graph[i][j] = INF;
				
	for(int i=1;i<=m;i++){//输入
		cin >> a >> b >> c;
		graph[a][b] = c;
	}
	
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			if(graph[i][j] != 0 && graph[i][j] != INF)
				cout << i << " " << j << " " << graph[i][j];
	
	return 0;
}
2.邻接链表
  • 完成
 #include<bits/stdc++.h>
using namespace std;

struct node{
	int to, w;//终点,边权
};

vector<node> v[105];

int main(){
	int n, m;//点数,边数
	int a, b, c;//起点,终点,边权
	cin >> n >> m;
	
	for(int i=1;i<=m;i++)//初始化
		v[i].clear();
		
	for(int i=1;i<=m;i++){//建边
		cin >> a >> b >> c;
		v[a].push_back(node{b, c});
	}
	
	for(int i=1;i<=n;i++)
		for(int j=0;j<v[i].size();j++)
			cout << i << " " << v[i][j].to << " " << v[i][j].w << endl;
	
	return 0;
}

3.链式前向星(边表)
  • 完成
 #include<bits/stdc++.h>
using namespace std;

const int INF = 1 << 30;

int head[105], num = 0;//head[i]:以i为起点的最后一条边的下标

struct node{
	int to;//终点
	int w;//边权
	int nextt;//上一条边的下标
}edge[105];

void insert_edge(int x, int y, int z){//插入边表
	edge[num].to = y;
	edge[num].w = z;
	edge[num].nextt = head[x];
	head[x] = num++;
}

int main(){
	int n, m;
	int a, b, c;
	cin >> n >> m;
	memset(head, -1, sizeof(head));
	
	for(int i=1;i<=m;i++){
		cin >> a >> b >> c;
		insert_edge(a, b, c);
	}
	
	for(int i=1;i<=n;i++)
		for(int j=head[i];~j;j = edge[j].nextt)
			cout << i << " " << edge[j].to << " " << edge[j].w << endl;
	
	return 0;
}

遍历

  • 完成
深搜遍历
  • 完成
 #include<bits/stdc++.h>
using namespace std;

int vis[105];//标记点是否被访问过
vector<int> v[105];
int s;//起点

void DFS(int u){
	vis[u] = 1;
	cout << u;
	for(int i=0;i<v[u].size();i++)
		if(vis[v[u][i]] == 0)
			DFS(v[u][i]);
}

int main(){
	int n, m;//点数,边数
	int a, b;//起点,终点
	cin >> n >> m;
	memset(vis, 0, sizeof(vis));
		
	for(int i=1;i<=m;i++){//建边
		cin >> a >> b;
		v[a].push_back(b);
	}
	
	s = 1;
	DFS(s);
	
	return 0;
}
广搜遍历
  • 完成
 #include<bits/stdc++.h>
using namespace std;

int vis[105];//标记点是否被访问过
vector<int> v[105];

queue<int> q;

void BFS(){
	int s = 1;
	q.push(s);
	vis[s] = 1;
	while(!q.empty()){
		int u = q.front();
		q.pop();
		cout << u;
		for(int i=0;i<v[u].size();i++){
			int V = v[u][i];
			if(!vis[V]){
				q.push(V);
				vis[V] = 1;
			}
		}
	}
}

int main(){
	int n, m;//点数,边数
	int a, b;//起点,终点
	cin >> n >> m;
	memset(vis, 0, sizeof(vis));
		
	for(int i=1;i<=m;i++){//建边
		cin >> a >> b;
		v[a].push_back(b);
	}
	
	BFS();
	
	return 0;
}

拓扑排序

  • 完成
#include<bits/stdc++.h>
using namespace std;
#define maxn 110

int n;
vector<int> a[maxn];//使用vector邻接表储存图信息
int into[maxn];//into数组表示节点入度值
vector<int> ans;//ans储存最后序列

void init(){//输入,初始化图
	cin >> n;
	int s, t;
	while(scanf("%d%d", &s, &t) == 2){
		a[s].push_back(t);
		into[t]++;
	}
}

queue<int> q;
 
void TPSort(){
	for(int i=1;i<=n;i++)
		if(into[i] == 0)
			q.push(i);
	while (!q.empty()){//使用BFS搜索
		int u = q.front();//取队首顶点u		
		q.pop();//将u删除
		ans.push_back(u);
		for(int i=0;i<a[u].size();i++){
			//将从u出发的边删除
			int v = a[u][i];
			into[v]--;//对应边的终点入度减1
			if (into[v] == 0)//如果v点入度为0,将v入队
				q.push(v);
		}
	}
	if(ans.size() < n)
		cout << -1;
	else
		for(int i=0;i<ans.size();i++)
			cout << ans[i] << " ";
}
 
int main() {
	init();
	TPsort();
 
	return 0;
	
}

最短路

  • 完成
Dijkstra
  • 完成

一个点到其他点(单源)

1.朴素
  • 完成
 
2.堆优化
  • 完成
#include<bits/stdc++.h>
using namespace std;

int head[100010], cnt, dis[100010], n, m, s, u, v, w;

priority_queue<pair<int, int> > q;

struct node{
	int v, w, next;
}edge[200010];

bool visit[100010];

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

void dijkstra(){
	while(!q.empty()){
		int num = q.top().second; 
		q.pop();
		if(visit[num])
			continue;
		visit[num] = 1;
		for(int i=head[num];i;i=edge[i].next)
			if(dis[edge[i].v] > dis[num] + edge[i].w){
				dis[edge[i].v] = dis[num] + edge[i].w;
				q.push(make_pair(-dis[edge[i].v], edge[i].v));
			}
	}
}

int main(){
	cin >> n >> m >> s;
	
	for(int i=1;i<=m;i++){
		cin >> u >> v >> w;
		add(u, v, w);
	}
	
	for(int i=1;i<=n;i++)
		dis[i] = 1e10;

	dis[s] = 0;
	q.push(make_pair(0, s));
	dijkstra();
	
	for(int i=1;i<=n;i++)
		cout << dis[i] << " ";
	
	return 0;
}
Bell-man Ford
  • 完成
 //"GmonkeYC!"是什么鬼
//已通过
#include<bits/stdc++.h>
using namespace std;

struct edge{
	int from, to, val;
};

int d[1004];
edge ed[40004];

int main(){
//	freopen("bellmanford.in", "r", stdin);
//	freopen("bellmanford.out", "w", stdout);
	
	ios::sync_with_stdio(false);
	
	int n, m, s;
	cin >> n >> m >> s;
	
	for(int i=1;i<=m;i++){
		int u, v, w;
		cin >> u >> v >> w;
		ed[i].from = u;
		ed[i].to = v;
		ed[i].val = w;
	}
	
//	for(int i=1;i<=m;i++){
//		cout << ed[i].from << " " << ed[i].to << " " << ed[i].val << endl;
//	}
	
	memset(d, 0x3f, sizeof(d));
	d[s] = 0;
	
	//求最短路(良心代码量)
	
	for (int i = 1; i < n; i++) 
		for (int j = 1; j <= m; j++)
			d[ed[j].to] = min(d[ed[j].to], d[ed[j].from] + ed[j].val); 
	
	//输出
			
	//bool flag = 0;
	for (int j = 1; j <= m; j++)
		if (d[ed[j].to] > d[ed[j].from] + ed[j].val){
			//flag = 1;
			cout << "GmonkeYC!";
			return 0;
		}
		
//	if(flag == 1){
//		cout << "GmonkeYC!";
//		return 0;
//	}
	
	for(int i=1;i<=n;i++){
		if(d[i] > 100000){
			cout << -1;
			continue;
		}
		cout << d[i] << endl;
	}
	
	return 0;
}
/*
memset(d, 0x3f, sizeof(d)), d[s] = 0; // 初始化
for (int i = 1; i < n; i++) // 共进行 n - 1 轮
	for (int j = 1; j <= m; j++)
		d[ed[j].to] = min(d[ed[j].to], d[ed[j].from] + ed[j].val); // 松弛操作
bool flag = 0;
for (int j = 1; j <= m; j++)
	if (d[ed[j].to] > d[ed[j].from] + ed[j].val) flag = 1;
// 判断最短路是否存在
return 0;
*/
SPFA
  • 完成
 #include<bits/stdc++.h>
using namespace std;
const int maxn = 10001;
const int maxm = 10001;

int head[maxn], cnt = 0;
struct node{
	int u, v, w, nextt;
}edge[maxm * 2];

void add(int u, int v, int w){
	edge[++cnt].u = u;
	edge[cnt].v = v;
	edge[cnt].w = w;
	edge[cnt].nextt = head[u];
	head[u] = cnt;
}

int n, m;
int dis[maxn], sum[maxn];
bool vis[maxn];
queue<int> q;

bool spfa(int u){
	memset(dis, 0x3f, sizeof(dis));
	memset(vis, 0, sizeof(vis));
	memset(sum, 0, sizeof(sum));
	dis[u] = 0;
	q.push(u);
	vis[u] = 1;
	sum[u]++;
	while(!q.empty()){
		int x = q.front();
		q.pop();
		vis[x] = 0;
		for(int i=head[x];i;i=edge[i].nextt){
			int t = edge[i].v;
			if(dis[t] > dis[x] + edge[i].w){
				dis[t] = dis[x] + edge[i].w;
				if(!vis[t]){
					if(++sum[t] >= n)
						return 1;
					vis[t] = 1;
					q.push(t);
				}
			}
		}
	}
	return 0;
}

void print(){
	for(int i=1;i<=n;i++)
		cout << dis[i] << " ";
}

int main(){
	int s, x, y, z;
	cin >> n >> m >> s;
	for(int i=1;i<=m;i++){
		cin >> x >> y >> z;
		add(x, y, z);
	}
	
	bool ans;
	if(!ans)
		print();
	else
		cout << "负环";

	return 0;
}
Floyd
  • 完成

任意两点(多源)

 #include<bits/stdc++.h>
using namespace std;

int main(){
//	freopen("floyd.in", "r", stdin);
//	freopen("floyd.out", "w", stdout);
	
	ios::sync_with_stdio(false);
	
	int n, m;
	cin >> n >> m;
	
	int f[n+4][n+4];
	memset(f, 0x3f, sizeof(f));
	
	for(int i=1;i<=n;i++){
		f[i][i] = 0;
	}
	
	for(int i=1;i<=m;i++){
		int u, v, w;
		cin >> u >> v >> w;
		f[u][v] = min(w, f[u][v]);
		f[v][u] = min(w, f[u][v]);
	}
	
	for (int k = 1; k <= n; k++) // 中间变量记得放外面枚举
		for (int i = 1; i <= n; i++)
			for (int j = 1; j <= n; j++)
				f[i][j] = min(f[i][j], f[i][k] + f[k][j]); 
				
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++)
			if(f[i][j] > 8000000)
				cout << -1 << " ";
			else
				cout << f[i][j] << " ";
		cout << endl;
	}
	
	return 0;
}
/*
for (int k = 1; k <= n; k++) // 中间变量记得放外面枚举
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
			f[i][j] = min(f[i][j], f[i][k] + f[k][j]); 
*/

最小生成树

  • 完成
//最小生成树:Prim算法+邻接矩阵储存
//复杂度:n^2
#include<bits/stdc++.h>
using namespace std;

int w[5001][5001];//边的权值
int Min[5001];//蓝点的最小边权
bool B[5001];//蓝点标记
int MST = 0;//最小生成树权值和

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout .tie(0);
	
//	freopen(".in", "r", stdin);
//	freopen(".out", "w", stdout);

	int n, m;//顶点数和边数
	cin >> n >> m;
	
	//初始化w
	memset(w, 127, sizeof(w));
	for(int i=1;i<=m;i++){
		int x, y, z;
		cin >> x >> y >> z;
		w[x][y] = min(w[x][y], z);
		w[y][x] = min(w[y][x], z);
	}
	
	//初始化Min, B;
	memset(Min, 127, sizeof(Min));//初始化为最大
	memset(B, 1, sizeof(B));//初始化为蓝点
	Min[1] = 0;
	
	//求解最小生成树
	for(int i=1;i<=n;i++){//寻找Min[k]最小的蓝点k
		int k = 0;
		for(int j=1;j<=n;j++)
			if(B[j] && Min[j] < Min[k])
				k = j;
		B[k] = 0;//洗白点k
		MST += Min[k];//累加生成树权值
		//修改与k相连的所有蓝点
		for(int j=1;j<=n;j++)
			if(B[j] && w[k][j] < Min[j])
				Min[j] = w[k][j];
	}
	
	bool mark = 0;
	for(int i=1;i<=n;i++)
		if(B[i])
			mark = 1;
	
	if(mark)
		cout << "orz";//图不连通
	else
		cout << MST;
	
	return 0;
}

哈密顿环

  • 完成
#include<bits/stdc++.h>
using namespace std;
const int mx = 10004;

int A[mx][mx];//邻接点存储
int num[mx];//计数器
bool visit[mx];//访问标记
int start, path[mx];//起点,路径
int n, m;//顶点数和边数
void print(int);

//last是上次访问的点,i是当前访问的点,step是步数
void dfs(int last, int i, int step){
//	cout << i << " ";
	path[step] = i;//记录路径
	visit[i] = 1;//标记i已访问
	for(int j=1;j<=num[i];j++){//循环i的邻接点
		//    回到起点           避免回头        走完所有点
		if(A[i][j] == start && A[i][j] != last && step == n){
			path[n+1] = start;
			print(n+1);//输出路径
		}
		if(!visit[A[i][j]])
			dfs(i, A[i][j], step+1);//深搜一步
	}
	visit[i] = 0;//回溯
}

void print(int step){
	for(int i=1;i<step;i++)
		cout << path[i] << "--";
	cout << path[step] << endl;
}

int main(){
	int x, y;
	n = 4, m = 5;
	int a[9][9] = {{1, 2}, {1, 3}, {2, 3}, {2, 4}, {3, 4}};
	
	for(int i=1;i<=m;i++){
		x = a[i-1][0];
		y = a[i-1][1];
		A[x][++num[x]] = y;
		A[y][++num[y]] = x;
	}
	
	cout << "哈密顿环" << endl;
	for(start=1;start<=n;start++){
		dfs(start, start, 1);
	}
	
	return 0;
}


ST表

  • 完成

用来求区间最值
O ( n l o g n ) O(n log n) O(nlogn)

#include<bits/stdc++.h>
using namespace std;

int st[100004][24];
int loglong[100004];
int main(){
	loglong[0] = -1;
	long long n, m, q;
	cin >> n >> m >> q;
//输入
	for(int i=1;i<=n;i++){
		cin >> st[i][0];
		loglong[i] = loglong[i/2]+1;//预处理log数组
	}
	
//预处理ST表
    for(int i=1;i<=loglong[n];i++){
        for(int j=1;j+(1<<i)-1<=n;j++){
			st[j][i]=max(stamax[j][i-1],stamax[j+(1<<(i-1))][i-1]);
//询问
    while(q--){
    	int l, r;
        cin>>l>>r;
        cout << max(st[l][logg[r-l+1]], st[r-(1<<logg[r-l+1])+1][logg[r-l+1]]);
	}
	return 0;	
}

线段树

  • 完成

用来求区间最值
O ( n l o g n ) O(n log n) O(nlogn)




数学

  • 完成

gcd(最大公因数)

  • 完成
手写
 int gcdd(int x, int y){
	return y?gcdd(y,x%y):x;
}
自带(c++14)
int a = __gcd(x, y);

lcm(最小公倍数)

  • 完成
    等于 a ∗ b / g c d ( a , b ) 等于a * b / gcd(a, b) 等于ab/gcd(a,b)

质数

  • 完成
判断
  • 完成
 int pd(int y) {
 	if(y<2) 
		return 0;
	else if(y==2) 
		return 1;
	for(int i=2; i*i<=y; ++i) 
		if(y%i==0)
			return 0;
	return 1;
}
前k个
  • 完成
bool isPrime[100000010];
//isPrime[i] == 1表示:i是素数
int Prime[6000010], cnt = 0;
//Prime存质数

void GetPrime(int n)//筛到n
{
	memset(isPrime, 1, sizeof(isPrime));
	//以“每个数都是素数”为初始状态,逐个删去
	isPrime[1] = 0;//1不是素数
	
	for(int i = 2; i <= n; i++)
	{
		if(isPrime[i])//没筛掉 
			Prime[++cnt] = i; //i成为下一个素数
			
		for(int j = 1; j <= cnt && i*Prime[j] <= n/*不超上限*/; j++) 
		{
        	//从Prime[1],即最小质数2开始,逐个枚举已知的质数,并期望Prime[j]是(i*Prime[j])的最小质因数
            //当然,i肯定比Prime[j]大,因为Prime[j]是在i之前得出的
			isPrime[i*Prime[j]] = 0;
            
			if(i % Prime[j] == 0)//i中也含有Prime[j]这个因子
				break; //重要步骤。见原理
		}
	}
}

快速幂

  • 完成
//a ^ b % p = res
long long res = 1;
for (; b; a = a * a % p, b >>= 1, num++) 
	if (b & 1) 
		res = res * a % p;


数据结构

  • 完成

链表

  • 完成
 #include<bits/stdc++.h>
using namespace std;

struct Node{
	int value;
	Node* next;
	//Node *right;
};

void insertNode(int i, Node *p){//插入
	Node* node = new Node;
	node->value = i;
	node->next = p->next;
	p->next = node;
}

void deleteNode(Node *p){//删除
	p->value = p->next->value;
	Node *t = p->next;
	p->next = p->next->next;
	delete t;
}

int main(){

	return 0;
}
STL
  • 完成
vector<int> v;
vector<int> ve[12];
v[3]
ve[12][4]
v.push_back(x);
ve[4].push_back(x);
  • 完成

队列

  • 完成
手写
  • 完成
int head = 1, tail = 0, q[N]; // 队头, 队尾, 元素
head++; // 弹出队头
q[++tail] = x; // 将x 入队
q[head] q[tail] // 取队头队尾
head <= tail // 判断队列是否非空
STL
  • 完成
queue<int> q; // 定义i n t 类型队列
q.front() // 取队头
q.pop(); // 弹出队头
q.push(x); // 将x 入队
q.empty() // 队列是否为空

单调队列

  • 完成
// 入队
for(int i=1;i<=n;i++) {
	while(head <= tail && a[q[tail]] > a[i])
		tail−−;
	while(head <= tail && q[head] <= i − k)
		head++;
	q[++tail] = i;
	// 此时a[q[head]]即为求的[i−k+1, i]最值。
}

优先队列(堆)

  • 完成
STL
  • 完成
priority_queue<int> q; // 大根堆(支持访问最大)
priority_queue<int, vector<int>, greater<int>> q; //(小根堆)
// 记不下小根堆其实也可用大根堆, 插入值的相反数, 取出后再变成相反数
q.push(x); // 加入x
q.top(); // 取堆顶,请注意堆空时会直接RE!
q.pop(); // 删除堆顶
q.empty() q.size() // 判空、求大小
手写二叉堆
  • 完成
#include<bits/stdc++.h>
using namespace std;
const int N = 100004;//结点数

int h[N], n;//树

void up(int x){//向上调整h[x]
	while (x > 1 && h[x] > h[x / 2]){
		swap(h[x], h[x / 2]);
		x /= 2;
	}
}

void down(int x){//向下调整h[x]
	while (x * 2 <= n){
		t = x * 2;
		if(t + 1 <= n && h[t + 1] > h[t]) 
			t++;
		if (h[t] <= h[x]) 
			break;
		swap(h[x], h[t]);
		x = t;
	}
}

int main(){
	
	return 0;
}

双端队列

  • 完成
//注:可用list替换,且占空间更小
deque<int> q; // 定义i n t 类型队列
q.front() // 取队头
q.pop_front(); // 弹出队头
q.pop_back(); // 弹出队尾
q.push_front(x); // 将x 从队头入队
q.push_back(x); // 将x 从队尾入队
q.empty() // 队列是否为空

  • 完成
手写
  • 完成
int s[N], top ;
// 入栈
s[++top] = x ;
// 出栈
top−−;
// 取栈顶
s[top]
// 判断是否空
(top == 0)
STL
  • 完成
// 定义栈s
stack<int> s;
// 加入x
s.push(x);
// 删除
s.pop();
// 取栈顶
s.top()
// 判断空
s.empty()

单调栈

  • 完成
// 入栈
for(int i=1;i<=n;i++){
	while(a[s[top]] <= a[i] && top)
		top−−;
	if(top)
		f[i] = s[top];
	else
		f[i] = 0;
	s[++top] = i;
}

映射(map)

  • 完成
map<string, int> m;
m["qwq"] = 4;

map<int, map<int, int> > a;//二维映射
a[4][12] = 1314;

集合(set)

  • 完成



动态规划(DP)

  • 完成

背包

  • 完成
01背包
  • 完成
不超过
  • 完成
#include<bits/stdc++.h>
using namespace std;
int main(){
	int n;
	cin >> n;//物品数量
	int w[n+4], v[n+4];//w :重量	v :价值
	for(int i=1; i<=n; i++)	cin >> w[i] >> v[i];
	int W;
	cin >> W;//背包容量
	
	int dp[W+4];
	memset(dp, 0, sizeof(dp));
	
	for(int i=1; i<=n; i++)
		for(int j=W; j>=w[i]; j--)
			dp[j] = max(dp[j], dp[j-w[i]] + v[i]);
	
	cout << dp[W];
	return 0;
}
正好装满
  • 完成
#include<bits/stdc++.h>
using namespace std;
int main(){
	int n;
	cin >> n;//物品数量
	int w[n+4], v[n+4];//w :重量	v :价值
	for(int i=1; i<=n; i++)	cin >> w[i] >> v[i];
	int W;
	cin >> W;//背包容量
	
	//注意初始化
	memset(dp, -127, sizeof(dp));
	dp[0] = 0;
	
	for(int i=1; i<=n; i++)
		for(int j=W; j>=w[i]; j--)
			dp[j] = max(dp[j], dp[j-w[i]] + v[i]);
	
	cout << dp[W];
	return 0;
}

完全背包
  • 完成
不超过
  • 完成
 #include<bits/stdc++.h>
using namespace std;

int dp[204];
int w[32], v[32];
int N, W;

int main(){
    cin>>W>>N;
    for(int i=1;i<=N;i++)cin>>w[i]>>v[i];
    
    memset(dp, 0, sizeof(dp));	
    
    for(int i=1;i<=N;i++)
        for(int j=w[i];j<=W;j++)
            dp[j] = max(dp[j], dp[j-w[i]]+v[i]);
    
    cout << dp[W];
    
    return 0;
}
正好装满
  • 完成
  #include<bits/stdc++.h>
using namespace std;

int dp[204];
int w[32], v[32];
int N, W;

int main(){
    cin>>W>>N;
    for(int i=1;i<=N;i++)cin>>w[i]>>v[i];
    
	//注意初始化
	memset(dp, -127, sizeof(dp));
	dp[0] = 0;
    
    for(int i=1;i<=N;i++)
        for(int j=w[i];j<=W;j++)
            dp[j] = max(dp[j], dp[j-w[i]]+v[i]);
    
    cout << dp[W];
    
    return 0;
}

多重背包
  • 完成
 #include<bits/stdc++.h>
using namespace std;
int main(){
	int n, W;
	cin >> n >> W;
	
	int w, v, s, ww[10004], vv[10004], cnt = 0, dp[W+4];
	memset(dp, 0, sizeof(dp));
	
	//输入+初始化
	for(int i=1;i<=n;i++){
		cin >> w >> v >> s;
		for(int j=1;j<=s;j <<= 1){
			ww[++cnt] = w * j;
			vv[cnt] = v * j;
			s -= j;
		}
		if(s){
			ww[++cnt] = w * s;
			vv[cnt] = v * s;
		}
	}

	//用01背包
	for(int i=1;i<=cnt;i++)
		for(int j=W;j>=1;j--)
			if(j >= ww[i])
				dp[j] = max(dp[j], dp[j-ww[i]] + vv[i]);
	
	//输出
	cout << dp[W];
	
	return 0;
}

树形背包
  • 完成
 

树形DP

  • 完成
 

区间DP

  • 完成
 

数位DP

  • 完成
 

状压DP

  • 完成
 


排序

  • 完成

自带:快排

  • 完成
bool cmp(int x, int y){
	return x > y;
}
 int main(){ 
	int n[10000];
	sort(n, n+10000);//从小到大
	sort(n, n+10000, cmp);//自己写,这里从大到小
	return 0}

冒泡排序

  • 完成
    O ( n 2 ) O(n^2) O(n2)
#include<bits/stdc++.h>
using namespace std;

int num[10000];

int main(){
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	
//	freopen(".in", "r", stdin);
//	freopen(".out", "w", stdout);

	int n;
	cin >> n;
	
	for(int i=1;i<=n;i++)
		cin >> num[i];
	
	for(int i=1;i<n;i++)
		for(int j=i+1;j<=n;j++)
			if(num[i] > num[j])
				swap(num[i], num[j]);
	
	for(int i=1;i<=n;i++)
		cout << num[i] << " ";

	return 0;
}

选择排序

  • 完成
    O ( n 2 ) O(n^2) O(n2)
#include<bits/stdc++.h>
using namespace std;

int num[10000];

int main(){
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	
//	freopen(".in", "r", stdin);
//	freopen(".out", "w", stdout);

	int n;
	cin >> n;
	
	for(int i=1;i<=n;i++)
		cin >> num[i];
		
	int minn, id;
	for(int i=1;i<n;i++){
		minn = 1000000000;
		for(int j=i;j<=n;j++)
			if(num[j] < minn){
				minn = num[j];
				id = j;
			}
		swap(num[i], num[id]);
	}
	
	for(int i=1;i<=n;i++)
		cout << num[i] << " ";

	return 0;
}

快速排序

  • 完成
    O ( n l o g n ) O(n log n) O(nlogn)
#include<bits/stdc++.h>
using namespace std;

int num[1000000];

void qsort(int l, int r){
	if(l >= r)
		return;
	int i = l, j = r, key = num[(i + j) / 2];
	while(i <= j){
		while(num[i] < key)
			i++;
		while(num[j] > key)
			j--;
		if(i <= j)
			swap(num[i++], num[j--]);
	}
	if(l < j)
		qsort(l, j);
	if(r > i)
		qsort(i, r);
	return;
}

int main(){
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	
//	freopen(".in", "r", stdin);
//	freopen(".out", "w", stdout);

	int n;
	cin >> n;
	
	for(int i=1;i<=n;i++)
		cin >> num[i];
	
	qsort(1, n);

	for(int i=1;i<=n;i++)
		cout << num[i] << " ";

	return 0;
}

归并排序

  • 完成
    O ( n l o g n ) O(n log n) O(nlogn)
#include<bits/stdc++.h>
using namespace std;

int num[100004];

void mergeSort(int left, int right){
	if(left == right)
		return;
	else{
		int mid = (left + right) / 2;
		
		mergeSort(left, mid);
		mergeSort(mid + 1, right);

		int left_size = mid - left + 1;
		int right_size = right - mid;
		int left_num[100004], right_num[100004];
	
		for(int i=left;i<=mid;i++)
			left_num[i - left + 1] = num[i];
		for(int i=mid+1;i<=right;i++)
			right_num[i - mid] = num[i];
	
		int i = 1, j = 1, k = left;
		while(i <= left_size && j <= right_size)
			if(left_num[i] < right_num[j])
				num[k++] = left_num[i++];
			else
				num[k++] = right_num[j++];
		while(i <= left_size)
			num[k++] = left_num[i++];
		while(j <= right_size)
			num[k++] = right_num[j++];
	}
	
}
int main(){
	int n;
	cin >> n;
	
	for(int i=1;i<=n;i++)
		cin >> num[i];
	
	mergeSort(1, n);

	for(int i=1;i<=n;i++)
		cout << num[i] << " ";
	
	return 0;
}


  • 完成
    在这里插入图片描述

建树

  • 完成
#include<bits/stdc++.h>
using namespace std;

 struct node{
	char data;
	int Left,Right;
}a[N];

int main(){
	cin>>n;
	char x,y,z;
	int root=0; // 记录根节点
	
	for (int i=1;i<=n;i++){
		cin >> x >> y >> z;
		if (!root)
			root = x-'a'+1;
		int t = x-'a'+1;
		a[t].data = x;
		if (y>='a' && y<='z')
			a[t].Left=y-'a'+1;
		if (z>='a' && z<='z')
			a[t].Right=z-'a'+1;
	}
	
	return 0;
}

遍历

  • 完成
先序
  • 完成
 void pre_order(int root){
	// 先序遍历:根左右
	if (root==0) return ;
	cout<<a[root].data<<" ";
	pre_order(a[root].Left);
	pre_order(a[root].Right);
}
中序
  • 完成
 void in_order(int root){
	// 中序遍历:左根右
	if (root==0) return ;
	in_order(a[root].Left);
	cout<<a[root].data<<" ";
	in_order(a[root].Right);
}
后序
  • 完成
 void post_order(int root){
	// 后序遍历:左右根
	if (root==0) return ;
	post_order(a[root].Left);
	post_order(a[root].Right);
	cout<<a[root].data<<" ";
}

LCA

  • 完成
 

二叉搜索树

  • 完成
 //完整注释版 二叉搜索树 
//本质:对于根节点,小的扔左边,大的扔右边
#include<bits/stdc++.h>
using namespace std;

#define ls tree[x].son[0]
#define rs tree[x].son[1]

const int N = 10010;
const int INF = 0x7fffffff;

//inline int read(){//快读
//	int r = 0; bool w = 0; char ch = getchar();
//	while(ch < '0' || ch > '9')
//		w = ch == '-' ? 1 : w, ch = getchar();
//	while(ch >= '0' && ch <= '9')
//		r = (r << 3) + (r << 1) + (ch ^ 48), ch =
//	getchar();
//	return w ? ~r + 1 : r;
//}

//左小右大!!!! 从小到大!!!!
struct Node{//一个节点:值,子树节点数,相等值计数,左右儿子下标
	int val, siz, cnt, son[2];
}tree[N];
int n, root, tot;//询问个数,根下标,节点个数

void add(int v){//插入
	if(!tot){//根节点
		root = ++tot;
		tree[tot].cnt = tree[tot].siz = 1;//cnt,siz初始都为1,初始化1
		tree[tot].son[0] = tree[tot].son[1] = 0;//初始化2
		tree[tot].val = v;//初始化3
		return;
	}
	int x = root, last = 0;//x:正在比的;last:父节点
	while(1){
		++tree[x].siz;//子树节点数+1
		if(tree[x].val == v){//与当前结点值相等
			++tree[x].cnt;//相等值计数+1
			break;//就做完了
		}
		last = x;//下一层
		x = tree[last].son[v > tree[last].val];//无子节点:x=0
		if(!x){//如果没有子节点
			//v > tree[last].val:大,1,右子树;小,0,左子树
			tree[last].son[v > tree[last].val] = ++tot;//连到父节点
			tree[tot].cnt = tree[tot].siz = 1;//初始化1
			tree[tot].son[0] = tree[tot].son[1] = 0;//初始化2
			tree[tot].val = v;//初始化3
			break;
		}
	}
}

int queryfr(int val){//求前驱(前驱定义为小于val,且最大的数)
	int x = root, ans = -INF;//没有:-INF
	while(1){
		if(x == 0)//找到底了
			return ans;//返回答案
		if(tree[x].val >= val){//x的值比val大(不可能在右子树里)
			if(ls == 0)//没有左子树
				return ans;
			x = ls;//找左子树(即更小的)
		}
		else{//x值比它小(不在左子树里,右子树更大,所以更优)
			if(rs == 0)//没有右子树
				return tree[x].val;//因为x比val小,所以返回
			ans = tree[x].val;//更新答案
			x = rs;//找右子树(更大、更优)
		}
	}
}

int queryne(int v){//求后继(后继定义为大于v,且最小的数)
	int x = root, ans = INF;//没有:INF
	while(1){
		if(x == 0)//找到底了
			return ans;//返回答案
		if(tree[x].val <= v){//x的值比v小(不可能在左子树里)
			if(rs == 0)//没有右子树
				return ans;
			x = rs;//找右子树(即更大的)
		}
		else{//x值比它大(不在右子树里,左子树更小,所以更优)
			if(ls == 0)//没有左子树
				return tree[x].val;//因为x比v大,所以返回
			ans = tree[x].val;//更新答案
			x = ls;//找左子树(更大、更优)
		}
	}
}

int queryrk(int rk){//求排名为rk的
	int x = root;
	while(1){
		if(x == 0)//找完了还没找到
			return INF;
		if(tree[ls].siz >= rk)//排名从小到大,左子树都比X结点小,
			x = ls;			  //总结点数>rk,在左子树内
		else if(tree[ls].siz + tree[x].cnt >= rk)//左子树不够,但加
			return tree[x].val;//x的数量够,返回x
		else{//还不够:右子树大,剩下的在右子树内
			rk -= tree[ls].siz + tree[x].cnt;
			x = rs;
		}
	}
}

int queryval(int v){//求比当前数小的数的个数,(x数的排名-1)
	int x = root, ans = 0;//ans是上方比v小的数量
	while(1){
		if(x == 0)//找到底了
			return ans;//返回
		if(tree[x].val == v)//当前结点是v,返回ans+左子树(左子树小)
			return ans + tree[ls].siz;
		else if(tree[x].val > v)//比v大
			x = ls;//在左子树里找
		else{//比v小
			ans += tree[ls].siz + tree[x].cnt;//加上左子树
			x = rs;//在右子树里找
		}	
	}
}

int main(){
	cin >> n;
	
	while(n--){
		int opt, x;
		cin >> opt >> x;
		if(opt == 1)
			printf("%d\n", queryval(x) + 1);
		if(opt == 2)
			printf("%d\n", queryrk(x));
		if(opt == 3)
			printf("%d\n", queryfr(x));
		if(opt == 4)
			printf("%d\n", queryne(x));
		if(opt == 5)
			add(x);
	}
	
	return 0;
}

并查集

  • 完成
 //并查集
//并查集性质:并查集产生的每一个集合都是一棵树
#include<bits/stdc++.h>
using namespace std;

//初始化
/*
for (int i=1;i<=n;i++)
	fa[i]=i;

*/

//查找
/*
1.朴素
(1)递推
int Find(int x){
	while(x!=fa[x])
		x=fa[x];
	return x;
}

(2)递归
int Find(int x){
	if(x==fa[x])
		return x;
	return Find(fa[x]);
}

2.优化
// 寻找根节点的路径压缩(递归写法)
int Find(int x){
	if (x==fa[x])
		return x;
	return fa[x]=Find(fa[x]);
	// 递归过程查找根节点,同时把根节点赋值给fa[x]
}
*/

//合并
/*
void Union(int a,int b){
	int faA=Find(a); // 查找a的根节点,记为faA
	int faB=Find(b); // 查找b的根节点,记为faB
	if (faA!=faB)
		Find(faA)=faB; // 合并
}

*/
//以下题目为 洛谷 P1551 亲戚
#include<bits/stdc++.h>
using namespace std;
const int N=5010;

int n,m,t;
int f[N]; // 点与父结点

int Find(int x){
	// 查找与修改当前点的父结点为根节点
	if (x != f[x])
		return f[x] = Find(f[x]);// 如果当前父结点不是根结
		//点,则递归查找
	return x; // 返回根节点
}

int main(){
	cin >> n >> m >> t;
	for (int i=1;i<=n;i++)
		f[i] = i; // 初始化父结点为自己
	
	int x, y; // 表示关系链
	for (int i=1;i<=m;i++){
		cin >> x >> y; // 输入关系 1 2
		f[Find(x)] = Find(y); // 查询并合并两点,将左图中的根节
		//点5合并到右图结点5(原来父结点是自己)的父结点修改为4
		// for (int i=1;i<=n;i++) cout<<f[i]<<" " ;可以查看过程
	}
	for (int i=1;i<=t;i++){
		cin >> x >> y; //检查两者是否有关系,即是否在一个集合
		f[x] = Find(x);
		f[y] = Find(y); // 查找两点的根节点
		if (f[x] == f[y])
			cout << "Yes" << endl; // 如果根节点一样,则在同一个集合
		else
			cout << "No" << endl;
	}
	return 0;
}


快读

  • 完成
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}


高精度

  • 完成
#include<bits/stdc++.h>
using namespace std;
const int N = 3000;

int x[N], y[N];
int c[N];
string a, b;
int num;

void mults(){ 
	num = a.size() + b.size() - 1;
	for(int i=0;i<num;i++){
		for(int j=0;j<=i;j++)
			c[i] += x[j] * y[i-j];
		if(c[i] >= 10){
			c[i + 1] += c[i] / 10;
			c[i] %= 10;	
		}
	}
	//去掉多余的前导零 
	for(int i=num;i>0;i--)
		if(c[i] == 0)
			num--;
		else
			break;
}

int main(){
	cin >> a >> b;
	memset(x, 0, sizeof(x));
	memset(y, 0, sizeof(y));
	
	for(int i =a.size()-1;i>=0;i--)
		x[a.size() - 1 - i] = a[i] -'0'; 	
	
	for(int i= b.size()-1;i>=0;i--)
		y[b.size() - 1 - i] = b[i] -'0'; 
	
	mults();
	
	for(int i=num;i>=0;i--)
		printf("%d", c[i]);
		
	return 0;
} 


评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值