第一讲 基础算法

参考常用代码模板1——基础算法

1. 快速排序

AcWing 785. 快速排序

void quick_sort(int q[], int l, int r)
{
	if(l >= r)return ;
	 
	int x = q[l + r >> 1], i = l - 1, j = r + 1; // 指针预留一个位置出来 
	while(i < j)
	{
		do i++; while(q[i] < x); //不能相等 
		do j--; while(q[j] > x);
		if(i < j) 
		{
			int t = q[i];
			q[i] = q[j];
			q[j] = t;
		} 
	}
	quick_sort(q, l, j); // 下标需要使用j,原因是之前X的选择使用了j,使用其他陷入无限循环 
	quick_sort(q, j + 1, r);
} 

AcWing 786. 第k个数

O(n)复杂度,对数组n仅作单边递归,等比数列求和

#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
#include<string.h>
using namespace std;
const int N = 1e5 + 10;
int q[N]; 
int quick_select(int l, int r, int k)
{
	if(l == r)return q[r];
	 
	int x = q[l + r >> 1], i = l - 1, j = r + 1; // 指针预留一个位置出来 
	while(i < j)
	{
		do i++; while(q[i] < x); //不能相等 
		do j--; while(q[j] > x);
		if(i < j) 
		{
			int t = q[i];
			q[i] = q[j];
			q[j] = t;
		} 
	}
	if (k <= j - l + 1)
	{
		return quick_select(l, j, k); // 下标需要使用j,原因是之前X的选择使用了j,使用其他陷入无限循环 
	}
	else 
	{
		return quick_select(j + 1, r, k - j - 1 + l);
	}

} 
int main()
{
	int n, k;
	
	cin >> n >> k;
	for(int i = 0; i < n; i++)scanf("%d", &q[i]);
	
	cout << quick_select(0, n-1, k) << endl;
	return 0;
} 

2. 归并排序

AcWing 787. 归并排序

void merge_sort(int q[], int l, int r)
{
	if(l >= r)return;
	
	int mid = l + r >> 1;
	
	merge_sort(q, l, mid);
	merge_sort(q, mid + 1, r); //记得加1 
	
	int i = l, j = mid + 1, k = 0;
	while(i <= mid && j <= r)
	{
		if(q[i] <= q[j])temp[k++] = q[i++];
		else temp[k++] = q[j++];
	}
	while(i <= mid)temp[k++] = q[i++];
	while(j <= r)temp[k++] = q[j++];
	
	for(i = l; i <= r; i++)q[i]=temp[i - l];
}

AcWing 788. 求逆序对数

#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
#include<string.h>
using namespace std;

const int N = 1e5 + 10;
int q[N]; 
int temp[N];
int n;
long long  num = 0;
 
void merge_sort(int q[], int l, int r)
{
	if(l >= r)return;
	
	int mid = l + r >> 1;
	
	merge_sort(q, l, mid);
	merge_sort(q, mid + 1, r); //记得加1 
	
	int i = l, j = mid + 1, k = 0;
	while(i <= mid && j <= r)
	{
		if(q[i] <= q[j])temp[k++] = q[i++];
		else 
		{
			temp[k++] = q[j++];
			if(mid >= i)num += (mid - i + 1);
		}
	}
	while(i <= mid)temp[k++] = q[i++];
	while(j <= r)temp[k++] = q[j++];
	
	for(i = l; i <= r; i++) q[i] = temp[i - l];
}
int main()
{
	scanf("%d", &n);
	
	for(int i = 0; i < n; i++)scanf("%d", &q[i]);
	
	merge_sort(q, 0, n - 1);
	
// 	cout << num << endl; //printf("%lld",num); long long 的输出需要用lld
printf("%lld",num);
	return 0;
} 

3. 二分

AcWing  789. 数的范围

#include<iostream> 

using namespace std;

const int N = 1e5 + 10;
int a[N];
int n, q, k;

int main()
{
	scanf("%d", &n);
	scanf("%d", &q);
	
	for(int i = 0; i < n; i++)scanf("%d", &a[i]);
	
	int l, r, mid;
	for(int i = 0; i < q; i++)
	{
		scanf("%d", &k);
		l = 0, r = n - 1;
		while(l < r)
		{
			mid = l + r >> 1;
			if(a[mid] >= k)r = mid;
			else l = mid + 1;
		}
		if(a[l] != k)cout<<"-1 -1"<<endl;
		else
		{
			cout<<l<<' ';
			l = 0, r = n - 1;
			while(l < r)
			{
				mid = l + r + 1>> 1;
				if(a[mid] <= k)l = mid;
				else r = mid - 1;
			}
			cout<<l<<endl;
		}
	}
	return 0;
}

AcWing 790. 数的三次方根

小数二分,边界值不需要加1减1

对于精度为n位小数时,循环条件设置为1e-n-2

include<iostream> 
#include<iomanip>
 
using namespace std;

int main()
{
	double n;
	cin >> n;
	
	double l, r, m = n, mid;
	if( m < 0 ) m *= -1;
	
	l = -1000, r = 1000;

	while( r - l > 1e-9)
	{
		mid = (l + r) / 2;//mid记得要更新,即在循环内部
		if( mid * mid * mid <= n )l = mid;
		else r = mid;
	}
	cout << fixed << setprecision(6) << l << endl;
	return 0;
}

4. 高精度

AcWing 791. 高精度加法

#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
#include<string.h>
using namespace std;
int main()
{
	string a, b;
	cin >> a >> b;
	vector<int> A, B, C;
	
	for(int i = a.size() - 1; i >= 0; i--)
	{
		A.push_back(a[i]-'0');	
	}
	for(int i = b.size() - 1; i >= 0; i--)
	{
		B.push_back(b[i]-'0');	
	}
	int leng = max(A.size(), B.size()),temp;
	temp = 0;
	for(int i = 0; i < leng; i++)
	{
		if(i < A.size()) temp += A[i];
		if(i < B.size()) temp += B[i];
		C.push_back(temp % 10);
		temp /= 10;
	}
	if(temp)C.push_back(temp);
	for(int i = C.size() - 1;i >= 0; i--)
		cout<<C[i];
	
	return 0;
} 

AcWing 792. 高精度减法

#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
#include<string.h>
using namespace std;
int main()
{
	string a, b;
	cin >> a >> b;
	vector<int> A, B, C;
	
	for(int i = a.size() - 1; i >= 0; i--)
	{
		A.push_back(a[i]-'0');	
	}
	for(int i = b.size() - 1; i >= 0; i--)
	{
		B.push_back(b[i]-'0');	
	}
	
	int negative = 0;
	if(a.length() > b.length())
	{
		
	}
	else if (a.length() < b.length())
	{
		negative = 1;
		vector<int> ttt = A;
		A = B;
		B = ttt;
	}
	else if (a.length() == b.length())
	{
		if(a < b)
		{
			negative = 1;
			vector<int> ttt = A;
			A = B;
			B = ttt;
		}
	}
	else
	{
		cout<<"0"<<endl;
		return 0;
	}
	int x, y;
	int temp = 0;
	for(int i = 0; i < A.size(); i++)
	{
		x = 0, y = 0;
		if(i < A.size()) x = A[i];
		if(i < B.size()) y = B[i];
		
		if(temp) 
		{
			x -= 1;
			temp = 0;	
		}
		if(x < y) 
		{
			temp = 1;
			x += 10;
		}
		C.push_back(x - y);
	}
	if(negative)cout<<"-";
	int first = 1;
	for(int i = C.size() - 1;i >= 0; i--)
	{
		if(first && C[i] == 0)
		{
			continue;
		}
		else
		{
			first = 0;
			cout << C[i];
		}	
	}
	if(first == 1) cout << "0" << endl; 
	return 0;
} 

AcWing 793. 高精度乘法

#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
#include<string.h>
using namespace std;
vector<int> add(vector<int> &A, vector<int> &B)
{
	vector<int> C;
	int leng = max(A.size(), B.size()), temp;
	temp = 0;
	for(int i = 0; i < leng; i++)
	{
		if(i < A.size()) temp += A[i];
		if(i < B.size()) temp += B[i];
		C.push_back(temp % 10);
		temp /= 10;
	}
	if(temp)C.push_back(temp);
	return C;
}
int main()
{
	string a, b;
	cin >> a >> b;
	vector<int> A, B, ans;
	
	for(int i = a.size() - 1; i >= 0; i--)
	{
		A.push_back(a[i]-'0');	
	}
	for(int i = b.size() - 1; i >= 0; i--)
	{
		B.push_back(b[i]-'0');	
	}
	
	if(a == "0" || b == "0")
	{
		cout<<"0"<<endl;
		return 0; 
	} 
	if (a.length() < b.length())
	{
		vector<int> ttt = A;
		A = B;
		B = ttt;
	}
	
	int x, y;
	int temp = 0;
	for(int i = 0; i < B.size(); i++)
	{
		x = B[i];
		temp = 0;
		if(i == 0)
		{
			for(int j = 0; j < A.size(); j++)
			{
				y = A[j];
				temp += x * y;
				ans.push_back(temp % 10);
				temp /= 10;
			}
			if(temp)ans.push_back(temp);
			if(ans.size() == 0)ans.push_back(0);
		}
		else
		{
			vector<int> C;
			for(int k = 0; k < i; k++)
				C.push_back(0);
			for(int j = 0; j < A.size(); j++)
			{
				y = A[j];
				temp += x * y;
				C.push_back(temp % 10);
				temp /= 10;
			}
			if(temp)C.push_back(temp);
			if(C.size() == 0)C.push_back(0);
			ans = add(ans, C);
		}
	}
	for(int i = ans.size() - 1;i >= 0; i--)	cout << ans[i];
	return 0;
} 

5. 前缀与差分

AcWing 795. 前缀和

#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
#include<string.h>
using namespace std;

const int N = 1e5 + 10;
int a[N], s[N];
int n, m;
int main()
{
	int l, r;
	cin >> n >> m;
	for(int i = 1; i <= n; i++)
		scanf("%d", &a[i]);
	
	s[1] = a[1];
	s[0] = 0;
	a[0] = 0;
	for(int i = 2; i <= n; i++)
		s[i] = s[i - 1] + a[i];
		
	for(int i = 0; i < m; i++)
	{
		scanf("%d%d", &l, &r);
		printf("%d\n",s[r] - s[l - 1]);
	}
	return 0;
} 

AcWing 796. 子矩阵的和

#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
#include<string.h>
using namespace std;

const int N = 1010;
int a[N][N], s[N][N];
int n, m, q;
int main()
{
	int x1, y1, x2, y2;
	cin >> n >> m >> q;
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= m; j++)
			scanf("%d", &a[i][j]);

	s[0][1] = 0, s[0][0] = 0, s[1][0] = 0;
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= m; j++)
			s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + a[i][j];
		
	for(int i = 0; i < q; i++)
	{
		scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
		printf("%d\n",s[x2][y2] - s[x2][y1 - 1] - s[x1 - 1][y2] + s[x1 - 1][y1 - 1]);
	}
	return 0;
} 

AcWing 797. 差分

#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
#include<string.h>
using namespace std;

const int N = 1e5 + 10;
int a[N], b[N] = { 0 };
int n, m;
int main()
{
	int l, r, c;
	cin >> n >> m;
	for(int i = 1; i <= n; i++)scanf("%d", &a[i]);

	for(int i = 1; i <= m; i++)
	{
		scanf("%d%d%d", &l, &r, &c);
		b[l] += c;
		b[r + 1] -= c;
	}
	
	for(int i = 1; i <= n; i++)b[i] += b[i - 1];
	for(int i = 1; i <= n; i++)printf("%d ", a[i] + b[i]);
	return 0;
} 

AcWing 798. 差分矩阵

#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
#include<string.h>
using namespace std;

const int N = 1e3 + 10;
int a[N][N], b[N][N] = { 0 };
int n, m, q;
int main()
{
	int x1, y1, x2, y2, c;
	cin >> n >> m >> q;
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= m; j++)
			scanf("%d", &a[i][j]);

	for(int i = 1; i <= q; i++)
	{
		scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &c);
		b[x1][y1] += c;
		b[x2 + 1][y1] -= c;
		b[x1][y2 + 1] -= c;
		b[x2 + 1][y2 + 1] += c;
	}
	
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= m; j++)
			b[i][j] += b[i - 1][j] + b[i][j - 1] - b[i - 1][j - 1]; //记得是+= 

	for(int i = 1; i <= n; i++)
	{
		for(int j = 1; j <= m - 1; j++)
			cout << a[i][j] + b[i][j] << " ";
		cout << a[i][m] + b[i][m] << "\n";
	}
		
	
	return 0;
} 

6. 双指针算法


AcWing 799. 最长连续不重复子序列

#include<iostream>
#include<string.h>

using namespace std;

const int N = 1e5 + 10;

int a[N], b[N] = { 0 };

int main()
{
	int ans = 0, n;
	
	scanf("%d", &n);
	
	for(int i = 0; i < n; i++)scanf("%d", &a[i]);
	
	for(int i = 0, j = 0; i < n; i++)
	{
		while(!b[a[j]] && j < n)
		{
			b[a[j]]++;
			j++;	
		}
		if(b[a[j]] || j == n)ans = max(ans, j - i);
		b[a[i]]--; 
	}
	printf("%d\n", ans);
	return 0;
}


AcWing 800. 数组元素的目标和

#include<iostream>
#include<string.h>

using namespace std;

const int N = 1e5 + 10;

int a[N], b[N];

int main()
{
	int n, m, x;
	
	scanf("%d%d%d", &n, &m, &x);
	
	for(int i = 0; i < n; i++)scanf("%d", &a[i]);
	
	for(int i = 0; i < m; i++)scanf("%d", &b[i]);
	
	for(int i = 0, j = m - 1; i < n && j >= 0; i++)
	{
		while(a[i] + b[j] > x && j >= 0) j--;
		if(a[i] + b[j] == x)
		{
			printf("%d %d\n", i, j);
			break;
		}
	}

	return 0;
}


AcWing 2816. 判断子序列

#include<iostream>
#include<string.h>

using namespace std;

const int N = 1e5 + 10;

int a[N], b[N];

int main()
{
	int n, m;
	
	scanf("%d%d", &n, &m);
	
	for(int i = 0; i < n; i++)scanf("%d", &a[i]);
	
	for(int i = 0; i < m; i++)scanf("%d", &b[i]);
	
	int i, j;
	
	for(i = 0, j = 0; i < n && j < m; i++, j++)
	{
		while(a[i] != b[j] && j < m) j++;
		if(j == m)break;  //必须要提前跳出循环,否则i有可能在不匹配时等于n 
	}
	
	if(i == n)cout << "Yes"<<endl;
	else cout<< "No" << endl;
	
	return 0;
}


7. 位运算


AcWing 801. 二进制中1的个数

#include<iostream>
#include<string.h>
#include<cmath> 

using namespace std;

const int N = 1e5 + 10;

int a[N];

int lowbit(int x)
{
	return x & -x; //lowbit(x)返回二进制的最后一位1
}

int main()
{
	int n;
	
	scanf("%d", &n);
	
	for(int i = 0; i < n; i++)scanf("%d", &a[i]);
	
	int i, j, k, num;
	
	for(i = 0; i < n; i++)
	{
		num = 0;
		while(a[i])
		{
			a[i] -= lowbit(a[i]);
			num++;
		}	
		printf("%d ", num);
	}
	return 0;
}


8. 离散化


AcWing 802. 区间和

#include<iostream>
#include<string.h>
#include<cmath> 
#include<vector>
#include<algorithm>

using namespace std;

const int N = 3e5 + 10;

int a[N] = { 0 }, s[N] = { 0 };

vector<int> all, xx, cc, ll, rr;

int mymap(int x)
{
	int l = 0, r = all.size() - 1, mid;
	
	while(l < r)
	{
		mid = l + r >> 1;
		if(all[mid] >= x)r = mid;
		else l = mid + 1;
	}
	return l + 1;
}
int main()
{
	int n, m, x, c, l, r, temp;

	scanf("%d%d", &n, &m);
	
	//首先需要读入所有需要映射的“大数” 
	for(int i = 0; i < n; i++)
	{
		scanf("%d%d", &x, &c);
		
		all.push_back(x), xx.push_back(x), cc.push_back(c);
	}
	
	for(int i = 0; i < m; i++)
	{
		scanf("%d%d", &l, &r);
		
		all.push_back(l), all.push_back(r), ll.push_back(l), rr.push_back(r);
	}

	sort(all.begin(), all.end()); //排序 

	all.erase(unique(all.begin(), all.end()), all.end()); //去重 

	//执行加c
	for(int i = 0; i < xx.size(); i++) 
	{
		temp = mymap(xx[i]);
		
		a[temp] += cc[i];
	}

	//前缀和
	for(int i = 1; i < N; i++)
		s[i] = s[i - 1] + a[i];
	
	for(int i = 0; i < ll.size(); i++)
	{
		l = mymap(ll[i]), r = mymap(rr[i]);
		printf("%d\n", s[r] - s[l - 1]);
	} 
	return 0;
}


9. 区间合并


AcWing 803. 区间合并

#include<iostream>
#include<string.h>
#include<cmath> 
#include<vector>
#include<algorithm>
#include <utility>

using namespace std;

const int N = 1e5 + 10;

vector<pair<int,int> > vv;

int main()
{
	int n, l, r;
	
	scanf("%d", &n);
	
	if(n == 0)
	{
		printf("%d", 0);
		return 0;
	}
	
	for(int i = 0; i < n; i++)
	{
		scanf("%d%d", &l, &r);
		vv.push_back(pair<int,int>(l,r));
	}
	
	sort(vv.begin(), vv.end());
	
	int st = vv[0].first, ed = vv[0].second, num = 1;
	
	for(int i = 1; i < vv.size(); i++)
	{
		l = vv[i].first, r = vv[i].second;
		
		if(l <= ed && r > ed)
		{
			ed = r;	
		} 
		else if (l > ed)
		{
			st = l, ed = r;
			num++;
		}
	}
	printf("%d", num);
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值