算法题-C++(2)

背书是万能的,不够聪明就背它个十万八千次! 0-0!

AcWing 785. 快速排序

C++

#include<iostream>
using namespace std;
const int N = 100005;
int n;
int a[N];
// 板子是老师的 但是我写成while的形式...
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)
    {
        while(q[++i]<x);
        while(q[--j]>x);
        if(i<j) swap(q[i],q[j]);
    }    
    //分块
    quick_sort(q,l,j);
    quick_sort(q,j+1,r);
}

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

AcWing 786. 第k个数

快排的迅速判断,只用递归一边就可以达成

C++

#include<iostream>
using namespace std;
const int N= 100005;
int n,k;
int a[N];

int quick_select(int q[],int l,int r,int k)
{
    if(l==r) return q[l];
    int x = q[l+r>>1], i = l-1, j = r+1;
    while(i<j)
    {
        // 这里如果写do while 是i++,j--
        while(q[++i]<x);
        while(q[--j]>x);
        if(i<j) swap(q[i],q[j]);
    }
    int sl = j-l+1;
    if(k<=sl) quick_select(q,l,j,k);
    // k-sl ...别再写错了球球了
    else quick_select(q,j+1,r,k-sl);
}

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

AcWing 787. 归并排序

 C++

#include<iostream>
using namespace std;
// #define N 1000010
const int N = 1000010;
int tmp[N];

void merge_sort(int q[],int l,int r)
{
	//先特殊判断
	if(l>=r) return;
	// 分界点x
	int mid = l+r>>1;
	//递归
	merge_sort(q,l,mid);
	merge_sort(q,mid+1,r);
	//分块2个数组 i:l-mid,j:mid+1-r
	int k =0, i = l, j = mid+1;
	while(i<=mid && j<=r)
	{
		if(q[i]<=q[j]) tmp[k++] = q[i++];
		else tmp[k++] = q[j++];
	}
	// 剩余的数据移过来... 谁剩下了就移过来...
	while(i<=mid) tmp[k++] = q[i++];
	while(j<=r) tmp[k++] = q[j++];
	//赋值 
	for(i=l,j=0;i<=r;i++,j++) q[i] = tmp[j];
}
int main()
{
	int n;
	scanf("%d",&n);
	int a[n];
	for(int i=0;i<n;i++)
		scanf("%d",&a[i]);
	merge_sort(a, 0 ,n-1);
	for(int i=0;i<n;i++)
		printf("%d ",a[i]);
	return 0;
 } 

AcWing 789. 数的范围 二分

还是背书快,但是理解的话画画图吧,这样才能理解,单纯背还是不得要领。

 C++

//https://blog.csdn.net/m0_46680603/article/details/119137088

// 对抗难题的最好方式就是背下来所有的答案
// 二分实在不会就背吧..
#include<iostream>
using namespace std;

int main()
{
	int n,m,k;
	cin>>n>>m;
	int a[n];
	for(int i=0;i<n;i++)
		cin>>a[i];
	for(int p=0;p<m;p++)
	{
		scanf("%d",&k);
		int l,r,mid;
		l = 0;
		r = n-1;
		// 查找大于等于x的数的下标 a[mid]>=x 
		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<<" ";
			// 这里不能直接算 不然算出来的结果会是一样的 
			//寻找小于等于x的数的下标 a[mid]<=x 
			l = 0;
			r = n-1; 
			while(l<r)
			{
				mid = l+r+1>>1;
				if(a[mid]<=k) l = mid;
				else r = mid - 1;
			}
			if(a[l]!=k) cout<<"-1 -1"<<endl;
			else cout<<l<<endl;
		}
	}
	return 0;
 } 

前缀和和差分系列

AcWing 795. 前缀和

#include<bits/stdc++.h>
using namespace std;
const int N = 100005;
int n, m;
int b[N],a[N];
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++)
	{
		b[i] = b[i-1]+a[i];
	}
	int l,r;
	for(int i=0;i<m;i++)
	{
		cin>>l>>r;
		cout<<b[r]-b[l-1]<<endl;
	}
//	for(int i=1;i<=n;i++)
//		cout<<b[i]<<" ";
	return 0;
}

AcWing 796. 子矩阵的和

//https://www.acwing.com/video/239/

// 接受两个坐标询问子矩阵的和 (x1,y1) (x2,y2) 
// s[i][j] 的含义: a[0-i][0-j]的和 a[i][j]这个点左上角的区域,包含这个点 
// 如何计算 以左上角 (x1,y1) 右下角 (x2,y2) 子矩阵里面所有的和 
// 画格子图理解会好一些... 
// target= s[x2,y2]-s[x1-1,y2]-s[x2,y1-1]+s[x1-1,y1-1] 
// 其中s[x1-,y1-1]被减两次要加回来一次 

// s 是子矩阵前缀和 
// s[i,j] = s[i-1,j]+s[i,j-1]-s[i-1,j-1]+a[i,j] 
#include<bits/stdc++.h>
using namespace std;
int n,m,q;
const int N=1010;
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++)
			cin>>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,x2,y1,y2;
		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>
using namespace std;
int n,m;
const int N = 100005;
int a[N],b[N];

void insert(int l,int r,int c)
{
    b[l]+=c;
    b[r+1]-=c;
}

int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=n;i++) insert(i,i,a[i]);
    while(m--)
    {
        int l,r,c;
        cin>>l>>r>>c;
        insert(l,r,c);
    }
    for(int i=1;i<=n;i++)
        b[i] += b[i-1];
    for(int i=1;i<=n;i++)
        cout<<b[i]<<" ";
    return 0;
}

AcWing 798. 差分矩阵

#include<bits/stdc++.h>
using namespace std;
const int N = 1005;
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;
}

//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

int main()
{
	cin>>n>>m>>q;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
		{
			cin>>a[i][j];
		// 构建差分数组
//			b[i][j]=a[i][j]-a[i-1][j]-a[i][j-1]+a[i-1][j-1]; 
		}	
// 构建差分数组
	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++)
		{
			a[i][j] = b[i][j]+a[i-1][j]+a[i][j-1]-a[i-1][j-1];
			cout<<a[i][j]<<" ";
		}
		cout<<endl;
	}
	return 0;
}

冶炼金属

 整除性质

#include<bits/stdc++.h>
using namespace std;
	//整除性质
	// 已知A ,B  V是所求  int(A/V)=B
	// B<= A/V <B+1
	// 1/B >= V/A > 1/(B+1)
	// A/B >= V > A/(B+1) 
	// Vmin = max(Vmin, int(A/(B+1))+1) Vmax = min(Vmax,A/B)
	//当A/(B+1)是小数时,V不能为0,所以加一  A/B就算是小数也满足>=的性质 
	// A/Bmax = 1e9/1 A/bmin=1/1 => V->[1,1e9] 
int n,a,b;
int v_min = 0,v_max = 1e9;
int main()
{
	cin>>n;
	for(int i=0;i<n;i++)
	{
		cin>>a>>b;
		v_min = max(v_min,a/(b+1)+1);
		v_max = min(v_max,a/b);
	}
	printf("%d %d",v_min,v_max); 
	return 0;
}

二分查找

//枚举能被最大整除和最小整除的数
#include<bits/stdc++.h>
using namespace std;
int n,a,b;
int v_min = 0,v_max = 1e9;
// 二分查找  这里右边界是可以取等的 所以后面的要-1 
int get(int a,int b)
{
	int l = 1,r = 1e9+1;
	while (l<r)
	{
		int mid = l+r>>1;
		if (a/mid<=b) r=mid;// 转换之后 => a/b<=mid ->r=mid 没毛病
		else l =mid+1; 
	}
	return l;
}

int main()
{
	cin>>n;
	while(n--)
	{
		cin>>a>>b;
		v_min = max(v_min,get(a,b));
		v_max = min(v_max,get(a,b-1)-1);
	}
	cout<<v_min<<" "<<v_max<<endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/daxuanzi515/article/details/129851705