NOIP前 基础算法模板

版权声明:转载请注明出处 https://blog.csdn.net/weixin_42557561/article/details/83795029
  • 二分(单调性)
  • 三分(单峰函数)
  • 离散化 (数据范围过大)
  • 中位数 O(n)
  • 逆序对(归并排序&树状数组)
  • 矩阵前缀和

二分

(整数域上的二分)

int l=1,r=1000,ans=0;
while(l<=r){
	int mid=l+r>>1;
	if(check(mid)) ans=mid,l=mid+1;
	else r=mid-1;
}
printf("%d",ans);

(实数域)

double l=1.0,r=1000.0;
while(r-l>=eps){
	double mid=(l+r)/2;
	if(check(mid)) l=mid;
	else r=mid;
}
printf("%lf",l);

三分

double l=1.0,r=1000.0;
while(r-l>=eps){
	double ll=l+(r-l)/3.0;
	double rr=r-(r-l)/3.0;
	if(calc(ll)<calc(rr)) l=ll;
	//如果三分得到的左端点比右端点劣,答案一定存在于这个左端点和r之间 
	else r=rr;
}
printf("%lf",l);

离散化

排序+去重
离散两部曲

sort(b+1,b+n+1);//排序 
int m=unique(b+1,b+n+1)-b-1;//去重 
for(int i=1;i<=n;++i)
	a[i]=lower_bound(b+1,b+m+1,a[i])-b;


中位数
nth_element()差不多是O(n)的效率,比手写快
注意每次搞完的时候只是把需要的放在了你想要的位置上,其他地方还是无序的

double get_middle_num(){
	if(n&1){
		nth_element(a+1,a+n/2+1,a+n+1);
		return a[n/2+1];
	}
	else{
		double x;
		nth_element(a+1,a+n/2,a+n+1);x=a[n/2];
		nth_element(a+1,a+n/2+1,a+n+1);
		x=(x+a[n/2+1])/2;
		return x;
	}
}

逆序对

树状数组
归并排序

#include<bits/stdc++.h>
#define in read()
#define N 300000
#define ll long long
using namespace std;
inline int read(){
	char ch;int f=1,res=0;
	while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;
	while(ch>='0'&&ch<='9') {
		res=(res<<3)+(res<<1)+ch-'0';
		ch=getchar();
	}
	return f==1?res:-res;
}
int n,a[N],t[N];
ll ans=0;
inline void mergecount(int l,int mid,int r){
	int num=l;//只是改变这个区间,不是1~n好吧!!!!
	int i=l,j=mid+1;
	while(i<=mid&&j<=r){
		if(a[i]>a[j]){
			t[num++]=a[j++];
			ans+=mid-i+1;
		}
		else t[num++]=a[i++];
	}
	while(i<=mid) t[num++]=a[i++];
	while(j<=r) t[num++]=a[j++];
	for(i=l;i<=r;++i) a[i]=t[i];
}
inline void solve(int l,int r){
	if(l==r) return;
	int mid=l+r>>1;
	solve(l,mid);
	solve(mid+1,r);
	mergecount(l,mid,r);
}
int main(){
	n=in;
	int i,j;
	for(i=1;i<=n;++i) a[i]=in;
	solve(1,n);
	cout<<ans;
	return 0;
}

矩阵前缀和

for(i=1;i<=n;++i)//插入
	for(j=1;j<=m;++j)
		sum[i][j]=num[i][j]+sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
ll ans=0;
for(i=r;i<=n;++i)//查询
	for(j=c;j<=m;++j)
		ans=max(ans,sum[i][j]-sum[i-r][j]-sum[i][j-c]+sum[i-r][j-c]);

猜你喜欢

转载自blog.csdn.net/weixin_42557561/article/details/83795029