二分水有点深、
这个蛮不错的:你常写的二分查找,真的是没有bug吗?
1、POJ2456 Aggressive cows (贪心加二分)
在CSDN以前写过这篇博客:https://blog.csdn.net/qq_40889820/article/details/81675301
这里改几发试试水
所求间距d的范围:下界肯定是1(C<=N),上界不确定,用INF表示一个很大的常数
a、(0,INF)
b、(-INF,INF)(和上面是一样的,都是开区间)
c、[1,INF)(左闭右开)
该返回哪个值得调整一下。

1 #include<iostream> 2 #include<algorithm> 3 using namespace std; 4 int N,C;//N为牛舍的间数,C为牛的头数 5 const int MAX_N=100010; 6 const int INF=1<<30; 7 int x[MAX_N];//排序后x[i]表示第i间牛舍的位置 8 bool islegal(int d)//是否可以安排牛的位置使得任意牛的间距都不小于d 9 { 10 int last=1;//上一头牛所在的牛舍 ,第一头牛放在第一间牛舍 11 for(int i=1;i<C;i++)//C-1头牛 12 { 13 int crt=last+1;//当前牛所在的牛舍 14 while(crt<=N&&x[crt]<x[last]+d) {crt++;} 15 if(crt==N+1) return false; 16 last=crt; 17 } 18 return true; 19 } 20 int main() 21 { 22 cin>>N>>C; 23 for(int i=1;i<=N;i++) cin>>x[i]; 24 sort(x+1,x+N+1); 25 int lb=1,ub=INF; 26 //[1,INF) 27 while(lb<ub) 28 { 29 int mid=(lb+ub)/2; 30 if(islegal(mid)) lb=mid+1; 31 else ub=mid; 32 } 33 cout<<lb-1; 34 }
2、POJ1743 Musical Theme (后缀数组+二分)
也写到后缀数组那儿了,两开花两开花:https://www.cnblogs.com/wangzhebufangqi/p/11317446.html

1 #include<bits/stdc++.h> 2 using namespace std; 3 const int MAXN=2e4+5; 4 const int INF=0x7fffffff; 5 int str[MAXN]; 6 int sa[MAXN],ra[MAXN],height[MAXN]; 7 int wa[MAXN],wb[MAXN],wc[MAXN],wd[MAXN]; 8 int read() 9 { 10 int s=1,x=0; 11 char ch=getchar(); 12 while(!isdigit(ch)) {if(ch=='-') s=-1;ch=getchar();} 13 while(isdigit(ch)) {x=10*x+ch-'0';ch=getchar();} 14 return x*s; 15 } 16 void GetSaRa(int n,int m)//倍增法 nlogn 17 { 18 int i,j,p,*x=wa,*y=wb,*t; 19 for(int i=0;i<m;++i) wd[i]=0; 20 for(int i=0;i<n;++i) wd[x[i]=str[i]]++; 21 for(int i=1;i<m;++i) wd[i]+=wd[i-1]; 22 for(int i=n-1;i>=0;--i) sa[--wd[x[i]]]=i; 23 for(j=1,p=1;p<n;j*=2,m=p) 24 { 25 for(p=0,i=n-j;i<n;++i) y[p++]=i; 26 for(i=0;i<n;++i) if(sa[i]>=j) y[p++]=sa[i]-j; 27 for(i=0;i<n;++i) wc[i]=x[y[i]]; 28 for(i=0;i<m;++i) wd[i]=0; 29 for(i=0;i<n;++i) wd[wc[i]]++; 30 for(i=1;i<m;++i) wd[i]+=wd[i-1]; 31 for(i=n-1;i>=0;--i) sa[--wd[wc[i]]]=y[i]; 32 for(swap(x,y),p=1,x[sa[0]]=0,i=1;i<n;++i) 33 x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+j]==y[sa[i]+j]?p-1:p++; 34 } 35 } 36 void GetHeight(int n) 37 { 38 int i,j,k=0; 39 for(i=1;i<=n;++i) ra[sa[i]]=i; 40 for(i=0;i<n;height[ra[i++]]=k) 41 for(k?k--:0,j=sa[ra[i]-1];str[i+k]==str[j+k];++k); 42 } 43 bool C(int n,int k)//是否存在两个长度为k的子串是相同的 44 { 45 int maxi=-1,mini=1<<30;//下标 46 for(int i=1;i<=n;++i) 47 { 48 if(height[i]<k)//分组 49 maxi=sa[i],mini=sa[i]; 50 else//组内是否有相同长度超过k的子串且距离大于k 51 { 52 maxi=max(maxi,max(sa[i],sa[i-1])); 53 mini=min(mini,min(sa[i],sa[i-1])); 54 if(maxi-mini>k) return true; 55 } 56 } 57 return false; 58 } 59 int main() 60 { 61 //freopen("1.txt","r",stdin); 62 int n,x,tmp; 63 while(scanf("%d",&n),n) 64 { 65 x=read();tmp=x; 66 for(int i=1;i<n;++i) 67 { 68 x=read(); 69 str[i-1]=x-tmp+100;//差分,避免桶排序中出现负的下标多加个100 70 tmp=x; 71 } 72 str[n-1]=0;n--; 73 GetSaRa(n+1,300); 74 GetHeight(n); 75 // for(int i=1;i<=n;++i) cout<<height[i]<<' ';cout<<endl; 76 if(!C(n,4)) 77 { 78 cout<<0<<endl; 79 continue; 80 } 81 //(-1,INF) 82 int l=-1,r=INF,mid; 83 while(l+1!=r) 84 { 85 mid=(l+r)>>1; 86 if(C(n,mid)) l=mid; 87 else r=mid; 88 } 89 cout<<l+1<<endl; 90 } 91 return 0; 92 }
开区间完事!
3、2018SWERC Blurred Pictures (ST+二分)(HNU内网访问)