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 }