题目传送门:https://www.luogu.org/problemnew/show/P1316
https://www.luogu.org/problemnew/show/P1182
今天真是令人悲伤的一天,写什么都写不出来,本来想找点st表的题做,在找题的路上意外看到了网络流,想到自己网络流完全不行就想研究这个,为了研究网络流,我想先去研究我同样薄弱的bfs,于是又遇到了我的一生之敌八数码,想把八数码解决就先练一下字符串哈希,结果就是直到现在,一事无成,只能说如下图
那么在睡觉前把前两天把我逼疯让我好好思考了一番的二分答案技巧在此做一个记录。通常来说,我们使用二分技巧适用于查询某个排好序序列里的值,复杂度为logn,那么这两道题则是将查找用于了另一个方面——直接查找答案,然后检查答案是否正确。本身这个技巧非常简单,但是很难想到(至少对于我这样的蒟蒻是这样吧),毕竟可以说这是在猜答案而不是解答案。不多说了,附上代码:
#1316
#include<stdio.h>
#include<stdlib.h>
int a[1000001]={0};
int n,m;
int quicksort(int left,int right)
{
int i,j,mid,t;
i=left;j=right;mid=a[(i+j)/2];
while(i<=j)
{
while(a[i]<mid) i++;
while(a[j]>mid) j--;
if(i<=j)
{
t=a[i];a[i]=a[j];a[j]=t;
i++;j--;
}
}
if(i<right) quicksort(i,right);
if(j>left) quicksort(left,j);
return 0;
}
int search(int x)
{
int i,num,pre;
pre=a[1];num=1;
for(i=2;i<=n;i++)
{
if(a[i]-pre>=x)
{
num++;pre=a[i];
}
if(num>=m)
return 1;
}
if(num<m) return 0;
else return 1;
}
int main()
{
int i,left,right,mid;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
quicksort(1,n);
left=1;right=a[n]-a[1];
while(left<right)
{
mid=(left+right+1)/2;
if(search(mid)==1) left=mid;
else right=mid-1;
}
printf("%d",right);
return 0;
}
#1182
#include<stdio.h>
#include<stdlib.h>
int a[1000001]={0};
int tmp=0,n,m;
int search(int x)
{
int i,num=0;
tmp=0;
for(i=1;i<=n;i++)
if(tmp+a[i]<=x)
tmp+=a[i];
else {tmp=a[i];num++;}
if(num<m)
return 1;
else return 0;
}
int main()
{
int i,j,left=-1,right=0,mid;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(a[i]>left) left=a[i];
right+=a[i];
}
while(left<right)
{
mid=(left+right)/2;
if(search(mid)==1) right=mid;
else left=mid+1;
}
printf("%d",left);
return 0;
}