acwing基础算法

基础算法板子

1.快速排序

 


快速排序

在这里插入图片描述

输入样例:

5
3 1 2 4 5

输出样例:

1 2 3 4 5

模板:

#include<iostream>
#include<cstdio>
using namespace std; 
const int N=10000+100;
int q[N],n;
void quick_sort(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) swap(q[i],q[j]);
	}
	quick_sort(l,j);
	quick_sort(j+1,r);
}
int main(){
	scanf("%d",&n);
	for(int i=0;i<n;i++) scanf("%d",&q[i]);
	
	quick_sort(0,n-1);
	
	for(int i=0;i<n;i++) printf("%d ",q[i]);
}


第K个数


 
 

2.归并排序


归并排序

在这里插入图片描述

输入样例:

5
3 1 2 4 5

输出样例:

1 2 3 4 5

模板:

#include<iostream>
#include<cstdio>
using namespace std;
const int N=100000+10;
int q[N],res[N],n;
void merge_sort(int l,int r){
	if(l>=r)  return;
	int mid=l+r>>1;
	merge_sort(l,mid);
	merge_sort(mid+1,r);
	int i=l,j=mid+1,k=0;
	while(i<=mid&&j<=r){
		if(q[i]<q[j])  res[k++]=q[i++];
		else           res[k++]=q[j++];
	}
	while(i<=mid) res[k++]=q[i++];
	while(j<=r)   res[k++]=q[j++];
	for(i=0,j=l;j<=r;j++) q[j]=res[i++];
}


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

 
 



 
 

3.二分

 


数的范围

在这里插入图片描述

输入样例:

6 3
1 2 2 3 3 4
3
4
5

输出样例:

3 4
5 5
-1 -1

模板:

#include<iostream>
#include<algorithm>
using namespace std;
const int MAX = 100005;
int asd[MAX];
int n,q;
int find_asdl(int x){
	int l=0,r=n-1;
	while(l<r){
		//cout<<" made in china "<<endl;
		int mid=l+r>>1;
		if(asd[mid]<x) l=mid+1;
		else r=mid;
	}
	if(asd[l]==x) return l;
	else return -1;
	
}
int find_asdr(int x){
	int l=0,r=n-1;
	while(l<r){
		//cout<<" made in china "<<endl;
		int mid=l+r+1>>1;
		if(asd[mid]<=x) l=mid;
		else r=mid-1;
	}
	if(asd[r]==x) return r;
	else return -1;
	
}
int main(){
	cin>>n>>q;
	for(int i=0;i<n;i++) cin>>asd[i];
	for(int i=0;i<q;i++){
		int x;
		cin>>x;
		cout<<find_asdl(x)<<" "<<find_asdr(x)<<endl;
		
	}
	return 0;
} 

 
 


数的三次方根

在这里插入图片描述

输入样例:

1000.00

输出样例:

10.000000

模板:

//浮点数二分查找 
#include<iostream>
using namespace std;
int main(){
	double n;
	cin>>n;
	
	double l=1e-4-10,r=1e4+10;
	while(r-l>1e8){
		double mid=(l+r)/2;
		if(mid*mid*mid>n) r=mid;
		else l=mid;
	}
	printf("%lf\n",l);
	return 0;
}


 
 
 


4.高精度


高精度加法

在这里插入图片描述

输入样例:

12
23

输出样例:

35

模板:

#include<iostream>
#include<vector>
#include<cstdio>
using namespace std;
const int N = 1e6 + 10;
vector<int>add(vector<int> &A,vector<int> &B){
	vector<int>C;
	if(A.size()<B.size()) return add(B,A);
	
	int t=0;
	for(int i=0;i<A.size();i++){
		if(i<A.size()) t+=A[i];
		if(i<B.size()) t+=B[i];
		C.push_back(t%10);
		t/=10;
	}
	if(t)C.push_back(1);
	return C;
}

int main()
{
	string a,b;
	vector<int> A,B;
	cin>>a>>b;
	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');
	
	vector<int> C=add(A,B);
	
	for(int i=C.size()-1;i>=0;i--) printf("%d",C[i]);
	return 0; 
}

 
 


高精度减法

在这里插入图片描述

输入样例:

32
11

输出样例:

21

模板:

//高精度减法
#include<iostream>
#include<vector>
#include<cstdio>
using namespace std;
bool panduan(vector<int> &A,vector<int> &B){
	if(A.size()!=B.size()) return A.size()>B.size();
	else
	{
		for(int i=A.size()-1;i>=0;i--){
			if(A[i]!=B[i]) return A[i]>B[i];
		}
		return true;
	}
	
}
vector<int> sub(vector<int> &A,vector<int> &B){
	vector<int> C;
	for(int i=0,t=0;i<A.size();i++){
		t=A[i]-t;
		if(i<B.size()) t-=B[i];
		C.push_back((t+10)%10);
		if(t<0) t=1;
		else t=0; 
	}
	while(C.size()>1&&C.back()==0) C.pop_back();
	return C;
}
int main(){
	string a,b;
	vector<int>A,B;
	cin>>a>>b;
	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(panduan(A,B)){
		vector<int> C=sub(A,B);
		for(int i=C.size()-1;i>=0;i--) printf("%d",C[i]);
	}else{
		vector<int> C=sub(B,A);
		printf("-");
		for(int i=C.size()-1;i>=0;i--) printf("%d",C[i]);
	}
	return 0;
} 

 
 


高精度乘法

在这里插入图片描述

输入样例:

2
3

输出样例:

6

模板:

//高精度乘法
#include<iostream>
#include<vector>
#include<cstdio>
using namespace std;
vector<int> mul(vector<int> &A,int b){
	vector<int> C;
	int t=0;
	for(int i=0;i<A.size()||t;i++){
		if(i<A.size()) t+=A[i]*b;
		C.push_back(t%10);
		t/=10;
	}
	return C;
}
int main(){
	string a;
	int b;
	cin>>a>>b;
	vector<int> A;
	for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
	
	vector<int> C=mul(A,b);
	for(int i=C.size()-1;i>=0;i--) printf("%d",C[i]);
	return 0; 
} 

 
 
 


高精度除法

在这里插入图片描述

输入样例:

7
2

输出样例:

3
1

模板:

//高精度除法 
#include<iostream>
#include<vector>
#include<cstdio>
#include<algorithm>
using namespace std;

vector<int> div(vector<int> &A,int b,int &r){
	vector<int> C;
	r=0;
	for(int i=A.size()-1;i>=0;i--){
		r=r*10+A[i];
		C.push_back(r/b);
		r%=b;
	}
	reverse(C.begin(),C.end());   //这玩意好用啊 reverse 要包含 algorithm 方便后的前导 0  
	while( C.size()>1 && C.back()==0 ) C.pop_back();  //前导 0  
	return C;
}
int main(){
	string a;
	int b;
	cin>>a>>b;
	vector<int> A;
	for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
	int r;
	vector<int> C=div(A,b,r);
	if(C.size())
	    for(int i=0;i<C.size();i++) printf("%d",C[i]);
	cout<<endl<<r<<endl;
	return 0; 
} 

 
 
 

5.前缀和与差分


前缀和

在这里插入图片描述

输入样例:

5 3
2 1 3 6 4
1 2
1 3
2 4

输出样例:

3
6
10

模板:

//前缀和
#include<iostream> 
#include<cstdio>
using namespace std;
const int N = 100010;
int n,m;
int a[N],s[N];
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	for(int i=1;i<=n;i++) s[i]=s[i-1]+a[i];
	
	while(m--){
		int l,r;
		scanf("%d%d",&l,&r);
		printf("%d\n",s[r]-s[l]);
	}
	return 0;
}

 
 
 


子矩阵的和

在这里插入图片描述

输入样例:

3 4 3
1 7 2 4
3 6 2 8
2 1 2 3
1 1 2 2
2 1 3 4
1 3 3 4

输出样例:

17
27
21

模板:

#include<iostream>
#include<iostream>
#include<cstdio>
using namespace std;
const int N = 1010;
int n,m,q;
int a[N][N],s[N][N];
int main(){
	scanf("%d%d%d",&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<=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];  //前缀求和 
			
	while(q--){
		int x1,y1,x2,y2;
		scanf("%d%d%d",&x1,&y1,&x2,&y2);
		printf("%d\n",s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1]);//算子矩阵的和 
	} 
	return 0;
}

 
 
 


差分

在这里插入图片描述

输入样例:

6 3
1 2 2 1 2 1
1 3 1
3 5 1
1 6 1

输出样例:

3 4 5 3 4 2

模板:

//一维差分 
#include<iostream>
using namespace std;
const int N = 10010;
int n,m;
int a[N],b[N]; //b 是 a 的前缀和     a 是 b 的差分 
void insert(int l,int r,int c){
	b[l]+=c;
	b[r + 1]-=c;
} 
int main(){
	scanf("%d%d",&n,&m);
	
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	
	for(int i=1;i<=n;i++) insert(i,i,a[i]);  // 构造 b 使得 为 a 的差分 
	
	while(m--){
		int l,r,c;
		scanf("%d%d%d",&l,&r,&c);
		insert(l,r,c);
	}
	for(int i=1;i<=n;i++) b[i]+=b[i-1];  // b 数组变成自己的前缀和
	
	for(int i=1;i<=n;i++) printf("%d",b[i]);
	
	return 0;
}


 
 
 


差分矩阵

在这里插入图片描述

输入样例:

3 4 3
1 2 2 1
3 2 2 1
1 1 1 1
1 1 2 2 1
1 3 2 3 2
3 1 3 4 1

输出样例:

2 3 4 1
4 3 4 1
2 2 2 2

模板:

//二维差分 
#include<iostream>
#include<cstdio>
using namespace std;
const int N = 1010;
int n,m,q;
int a[N][N],b[N][N];
// 差分 的 核心 
void insert(int x1,int y1,int x2,int y2,int c){
	b[x1][y1]+=c;
	b[x2+1][y1]-=c;
	b[x1][y2+1]-=c;
	b[x2+1][y2+1]+=c; 
} 
int main(){
	scanf("%d%d%d",&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<=n;i++)
	    for(int j=1;j<=m;j++)
	        insert(i,j,i,j,a[i][j]);
	        
	while(q--){
		int x1,y1,x2,y2,c;
		cin>>x1>>y1>>x2>>y2>>c;
		insert(x1,y1,x2,y2,c);
	}
	
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++) printf("%d ",b[i][j]);
		puts("");
	}
	return 0;
	
}

 
 
 


6.双指针算法

最长连续不重复子序列

在这里插入图片描述

输入样例:

5
1 2 2 3 5

输出样例:

3

模板:

//最长连续不重复子序列
#include<iostream>
#include<cstdio>
using namespace std;
const int N = 100010;
int n;
int a[N],s[N];
int main(){
	cin>>n;
	for(int i=0;i<n;i++) cin>>a[i];
	int res = 0;
	
	for(int i=0,j=0;i<n;i++){  //操作有点巧妙 
		s[a[i]]++;
		while(s[a[i]]>1){
			s[a[j]]--;
			j++;
		}
		res=max(res,i-j+1);
		
	}
	cout<<res<<endl;
	return 0; 
}

 
 
 


数组元素的目标和

 
 


7.位运算


二进制中1的个数

在这里插入图片描述

输入样例:

5
1 2 3 4 5

输出样例:

1 1 2 1 2

模板:

// lowbit操作 : 返回 x 的最后一位 1
//二进制中 1 的个数 
#include<iostream>
#include<cstdio>
using namespace std;
int lowbie(int x){   //lowbit x 可以返回 x 的最后一位 1  
	return x & -x;   // & 与运算符  -x = ~x+1(取反 x +1) 
}

int main(){
	int n;
	cin>>n;
	while(n--){
		int x;
		cin>>x;
		
		int res=0;
		while(x) x-=lowbie(x) res++;
		
		cout<<res<<endl;
	}
}

 
 


8.离散化

区间和

在这里插入图片描述

输入样例:

3 3
1 2
3 6
7 5
1 3
4 6
7 8

输出样例:

8
0
5

模板:

//离散化   
//区间和 
#include<iostream>
#include<cstdio>
#include<vector> 
#include<algorithm> 
using namespace std;
const int N = 300010;
typedef pair<int,int> PII;
int n,m;
int a[N],s[N];
vector<int>alls;
vector<PII>add,query;
int find(int x){
	int l=0,r=alls.size()-1;
	while(l<r){
		int mid=r+l>>1;
		if(alls[mid]>=x) r=mid;
		else l=mid+1;
	}
	return r+1;
}
//vector<int>::iterator unique(vector<int> &a){
//	int j=0;
//	for(int i=0;i<a.size();i++)
//	    if(!i||a[i]!=a[i-1])
//	        a[j++]=a[i];
//	        
//	return a.begin()+j;
//}
int main(){
	cin>>n>>m;
	for(int i=0;i<n;i++){
		int x,c;
		cin>>x>>c;
		add.push_back({x,c});
		
		alls.push_back(x);  
	}
	for(int i=0;i<m;i++){
		int l,r;
		cin>>l>>r;
		query.push_back({l,r});
		
		alls.push_back(l);
		alls.push_back(r);
		   
	}
	//去重
	sort(alls.begin(),alls.end());  //unique 返回去重后的数组最后一个元素 
	alls.erase(unique(alls.begin(),alls.end()),alls.end());
	
	//处理插入
	for(auto item : add){
		int x=find(item.first);
		a[x]+=item.second;
	} 
	//预处理前缀和
	for(int i=1;i<=alls.size();i++)  s[i]=s[i-1]+a[i];
	
	//处理询问
	for(auto item :query){
		int l=find(item.first),r=find(item.second);
		cout<<s[r]-s[l-1]<<endl;
	}
	return 0;
}


 
 

9.区间合并


区间合并

在这里插入图片描述

输入样例:

5
1 2
2 4
5 6
7 8
7 9

输出样例:

3

模板:

//区间合并
#include<iostream>
#include<cstdio>
#include<vector> 
#include<algorithm>
using namespace std;
const int N = 100010;
int n;
typedef pair<int,int>PII;
vector<PII> segs;
//双指针 
void merge(vector<PII> &segs){
	vector<PII> res;
	sort(segs.begin(),segs.end());  //C++默认先以 first 排序再以 second 排序 
	int st=-2e9,ed=-2e9;
	for(auto seg : segs)
	    if(ed<seg.first){
	    	if(st!=-2e9) res.push_back({st,ed});
			st=seg.first,ed=seg.second; 
		}
		else ed=max(ed,seg.second);
	if(st!=-2e9) res.push_back({st,ed});
	
	segs=res; 
}
int main(){
	cin>>n;
	for(int i=0;i<n;i++){
		int l,r;
		cin>>l>>r;
		segs.push_back({l,r}); 
	}
	merge(segs);
	cout<<segs.size()<<endl;
	return 0;
}

 
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值