新学知识:
T1:快速排序
快速排序(时间复杂度是O(nlog(n),有时会退化成O(n2))
取一个基准值,使基准值左边的数都小于基准值,基准值右边的数都大于基准值。
快速排序的代码:
void quick_sort(int l,int r){
if(l==r){
return;//在void函数里面,return 0;
可以写成return;
}
int x=f[l+r>>1],i=l-1,j=r+1;
while(i<j){
do i++;while(f[i]<x);
do j --;while(f[j]>x);
}
quick_sort(l,j),quick_sort(j+1,r);
}
T2:归并排序
归并排序,时间复杂度是O(nlog(n))
把一个数组平均分半,直到分成一个数字,再把两个数字分成一组,两个数字之间排序,排号后把两组排在一起,以此类推,排完为止。
归并排序的代码:
void merge_sort(int q[],int l,int r){
if(l>=r){
return;//在void函数里面,return 0;
可以写成return;
}
int mid=(l+r)/2;//向下取整
merge_sort(q,l,mid);
merge_sort(q,mid+1,r);
int k=0,i=1,j=mid+1;
while(i<=mid&&j<=r){
if(q[i]<=q[j]){
temp[k]=q[i];
k++;
i++;
}else{
temp[k]=q[j];
k++;
j++;
}
}
while(i<=mid){
temp[k++]=q[i++];
}
while(j<=r){
temp[k++]=q[j++];
}
for(int i=1,j=0;i<=r;i++,j++){
q[i]=temp[j];
}
}
T3:二分法
二分法指把一个有序的数组对半分开,取一个中间值,和要求的数字进行比较,如果中间值大于要求的数,那么判断的范围就缩短到了中间值的左边,否则判断的范围就是中间值的右边,以此类推,直到找到这个数字为止。
二分法的好处:每一次判断,判断的范围就缩短到一半。
二分法的代码:
bool check1(int mid){//mid是中间值
if(a[mid>=x){
return true;
}else{
return false;
}
}
int bs1(int l,int r){
while(l<r){
int mid=(l+r)>>1;//向下取整
if(check(mid)){
l=mid;
}else{
r=mid-1;
}
}
return l;
}
bool check2(int mid){
if(a[mid]<=x){
return true;
}else{
return false;
}
}
int bs2(int l,int r){
while(l<r){
int mid=(l+r+1)>>1;//向上取整
if(check(mid)){
l=mid;
}else{
r=mid-1;
}
}
return l;
}
T2二分查找
二分查找指把一个有序的数组对半分开,取一个中间值,和要求的数字进行比较,如果中间值大于要求的数,那么判断的范围就缩短到了中间值的左边,否则判断的范围就是中间值的右边,以此类推,直到找到这个数字为止。
二分查找代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
long long n,m,maxn,sum,a[N];
bool check(int mid){
for(long long i=0;i<n;i++){
if(a[i]>mid){
sum+=a[i]-mid;
}
}
return sum>=m;
}
int main(){
cin>>n>>m;
for(long long i=0;i<n;i++){
cin>>a[i];
if(a[i]>maxn){
maxn=a[i];
}
}
long long l=0,r=maxn;
while(l<r){
long long mid=l+r+1>>1;
if(check(mid)){
l=mid;
sum=0;
}else{
r=mid-1;
sum=0;
}
}
cout<<l;
return 0;
}
此处以伐木工为例
定义l等于最小值,r等于最大值,求最小值和最大值中间的值,缩小判断范围,sum累加求和,判断是否大于m后输出。