hihocoder 193周 修补木桶
1 /* 2 Source :hihocoder193周 修补木桶 3 Problem :一个圆形的木桶由n块木板围成,可以使用一种操作把连续的一段长度为L的区间中的木板变成无限长,操作可以使用m次,问最终最短的木板是多长。n<=1000,L<=20,m*L<n 4 Solution :直接计算较为困难,考虑一个简单一点的问题:如果知道了最终最短木板的长度,那么把这n块木板变成满足条件的最小操作次数是多少次。如果是一个序列,那么我们可以从 5 第一个位置贪心的枚举,这样可以求得最终需要的次数。对于一个环,拆成n条链分别判断。 6 其次,我们可以发现随着最终最短木板长度的增加,需要的操作次数是递减的。于是可以二分最终最短木板的长度。 7 Date :2018-08-16-15.32 8 */ 9 10 #include <bits/stdc++.h> 11 using namespace std; 12 13 typedef long long LL; 14 const int MAXN = 100005; 15 const LL MOD7 = 1e9+7; 16 17 int a[2005]; 18 int ans[1005]; 19 int n,m,Len; 20 21 22 bool check(int x) 23 { 24 for (int i=1;i<=Len;++i) 25 { 26 int t=0; 27 for (int j=i;j<i+n;++j) 28 { 29 if (a[j]<x) 30 { 31 ++t; 32 j+=Len-1; 33 } 34 } 35 if (t<=m) return true; 36 } 37 return false; 38 } 39 40 int main() 41 { 42 #ifndef ONLINE_JUDGE 43 freopen("test.txt","r",stdin); 44 #endif // ONLINE_JUDGE 45 scanf("%d%d%d",&n,&m,&Len); 46 { 47 for (int i=1;i<=n;++i) 48 { 49 scanf("%d",&a[i]); 50 ans[i]=a[i]; 51 } 52 for (int i=1;i<=n;++i) a[n+i] = a[i]; 53 sort(ans+1,ans+1+n); 54 int l=1,r=n; 55 int mid; 56 while (l<=r) 57 { 58 mid=(l+r)/2; 59 // printf("l=%d r=%d mid=%d check(%d)=%d\n",l,r,mid,ans[mid],check(ans[mid])); 60 if (check(ans[mid])) l=mid+1; 61 else r=mid-1; 62 } 63 printf("%d\n",ans[l-1]); 64 } 65 return 0; 66 }