E - Range Minimum Queries
Time limit : 2sec / Memory limit : 1024MB
Score : 600 points
Problem Statement
You are given an integer sequence of length and an integer . You will perform the following operation on this sequence times:
- Choose a contiguous subsequence of length , then remove the smallest element among the elements contained in the chosen subsequence (if there are multiple such elements, choose one of them as you like).
Let and be the values of the largest and smallest element removed in the operations. You would like to be as small as possible. Find the smallest possible value of when the operations are performed optimally.
Constraints
All values in input are integers.
Input
Input is given from Standard Input in the following format:
…
Output
Print the smallest possible value of .
Samples
Input | Output |
---|---|
5 3 2 4 3 1 5 2 |
1 |
10 1 6 1 1 2 3 5 8 13 21 34 55 |
7 |
11 7 5 24979445 861648772 623690081 433933447 476190629 262703497 211047202 971407775 628894325 731963982 822804784 |
451211184 |
In the first operation, whichever contiguous subsequence of length 3 we choose, the minimum element in it is . Thus, the first operation removes and now we have . In the second operation, it is optimal to choose as the contiguous subsequence of length and remove . In this case, the largest element removed is , and the smallest is , so their difference is .
解题思路
如果从正面来想,最大值
和最小值
都在变,所以不好解决。
于是我们可以固定最小值
,每次找符合要求的最小的
就行了。
具体来说,从小到大枚举最小值
,对于每次枚举的
:我们可以找到一些区间,满足区间长度
大于等于
并且区间内的所有数都大于等于
,于是这个区间内的前
小都有可能被选进答案,记录下这些可能值后,排序就可以找到对于当前的
最小的
是多少,用
更新
即可。
时间复杂度:枚举是 的,每次枚举中查找可能值+排序是 的,所以总复杂度是
Code
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 2005;
int n, k, q, a[N], ans = 1e9+5, t[N], b[N], c[N];
void cal(int mn){
int l = 1, r = 1;
b[0] = 0;
while(l <= n){
c[0] = 0;
while(a[l] < mn && l <= n) l++;
r = l;
while(a[r] >= mn && r <= n) r++;
for(int i = l; i < r && i <= n; i++)
c[++c[0]] = a[i];
if(c[0] >= k){
sort(c+1, c+c[0]+1);
for(int i = 1; i <= c[0] - k + 1; i++)
b[++b[0]] = c[i];
}
l = r;
}
sort(b+1, b+b[0]+1);
if(b[0] >= q) ans = min(ans, b[q] - b[1]);
}
int main(){
scanf("%d%d%d", &n, &k, &q);
for(int i = 1; i <= n; i++){
scanf("%d", &a[i]);
t[i] = a[i];
}
sort(t+1, t+n+1);
for(int i = 1; i <= n; i++)
cal(t[i]);
printf("%d\n", ans);
return 0;
}