二分习题集

二分水有点深、

这个蛮不错的:你常写的二分查找,真的是没有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 }
View Code

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 }
View Code

开区间完事!

3、

猜你喜欢

转载自www.cnblogs.com/wangzhebufangqi/p/11328034.html