NOIP模板复习——基础算法

二分

求满足条件的最小值

while(l<r)
{
	int mid=(l+r)>>1;
	if(check(mid))  r=mid;
	else  l=mid+1;
}

求满足条件的最大值

while(l<r)
{
	int mid=(l+r+1)>>1;
	if(check(mid))  l=mid;
	else  r=mid-1;
}

实数域上的二分(可以用 e p s eps ,也可以二分 100 100 次)

while(l+eps<r)
{
	double mid=(l+r)/2;
	if(check(mid))  r=mid;
	else  l=mid;
}

三分

求单峰函数最大值

while(r-l>=eps)
{
	m1=l+(r-l)/3;
	m2=r-(r-l)/3;
	if(f(m2)-f(m1)>=eps)  l=m1;
	else  r=m2;
}

求最小值和求最大值差不多,注意一下好点和坏点之前的关系就行了

逆序对

分治+归并排序

long long merge(int l,int r,int mid)
{
	long long ans=0;
	int i,b1=0,c1=0,b2=1,c2=1;
	for(i=l;i<=mid;++i)  b[++b1]=a[i];
	for(i=mid+1;i<=r;++i)  c[++c1]=a[i];
	for(i=l;i<=r;++i)
	{
		if(b1>=b2&&(c1+1==c2||b[b2]<=c[c2]))
		  a[i]=b[b2++];
		else
		{
			a[i]=c[c2++];
			ans+=b1-b2+1;
		}
	}
	return ans;
}
long long solve(int l,int r)
{
	if(l==r)  return 0;
	int mid=(l+r)>>1;
	long long ans=0;
	ans+=solve(l,mid);
	ans+=solve(mid+1,r);
	ans+=merge(l,r,mid);
	return ans;
}

树状数组(只贴最核心的三行,其他的都是树状数组基本操作)

for(i=1;i<=n;++i)
{
	scanf("%d",&x);
	add(x,1);
	ans+=i-sum(x);
}

进制转换

十进制转其他进制( x x 为原十进制数, n n 为要转换的进制)

int pos=0;
while(x!=0)
{
	a[++pos]=x%n;
	x/=n;
}
for(i=pos;i;--i)
{
	if(a[i]>10)  printf("%c",a[i]-10+'A');
	else  printf("%d",a[i]);
}

其他进制转十进制( a a 数组存的是原来的进制数,下标从 1 1 开始, n n 为原来的进制, x x 是转换后的十进制数)

for(i=1;i<=l;++i)
{
	if(a[i]>='0'&&a[i]<='9')  s=a[i]-'0';
	else  s=a[i]-'A'+10;
	x=x*n+s;
}

离散化

a a 数组是离散化后的数组,起初所有的 a i = b i a_i=b_i

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

中位数

可以直接用 nth_element 实现

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+=a[n/2+1];
	x/=2;
	return x;
}

猜你喜欢

转载自blog.csdn.net/forever_dreams/article/details/83793105