[AtCoder ARC098]E - Range Minimum Queries

E - Range Minimum Queries

Time limit : 2sec / Memory limit : 1024MB
Score : 600 points

Problem Statement

You are given an integer sequence A A of length N and an integer K K . You will perform the following operation on this sequence Q times:

  • Choose a contiguous subsequence of length K K , then remove the smallest element among the K elements contained in the chosen subsequence (if there are multiple such elements, choose one of them as you like).

Let X X and Y be the values of the largest and smallest element removed in the Q Q operations. You would like XY to be as small as possible. Find the smallest possible value of XY X − Y when the Q Q operations are performed optimally.

Constraints

1N2000
1KN 1 ≤ K ≤ N
1QNK+1 1 ≤ Q ≤ N − K + 1
1Ai109 1 ≤ A i ≤ 10 9
All values in input are integers.

Input

Input is given from Standard Input in the following format:

N N K Q Q
A1 A2 A 2 AN A N

Output

Print the smallest possible value of XY X − Y .

Samples

InputOutput
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 1 1 . Thus, the first operation removes A3=1 and now we have A=(4,3,5,2) A = ( 4 , 3 , 5 , 2 ) . In the second operation, it is optimal to choose (A2,A3,A4)=(3,5,2) ( A 2 , A 3 , A 4 ) = ( 3 , 5 , 2 ) as the contiguous subsequence of length 3 3 and remove A4=2. In this case, the largest element removed is 2 2 , and the smallest is 1, so their difference is 21=1 2 − 1 = 1 .


解题思路

如果从正面来想,最大值 X X 和最小值 Y 都在变,所以不好解决。
于是我们可以固定最小值 Y Y ,每次找符合要求的最小的 X 就行了。
具体来说,从小到大枚举最小值 Y Y ,对于每次枚举的 Y:我们可以找到一些区间,满足区间长度 len l e n 大于等于 K K 并且区间内的所有数都大于等于 Y,于是这个区间内的前 lenK+1 l e n − K + 1 小都有可能被选进答案,记录下这些可能值后,排序就可以找到对于当前的 Y Y 最小的 X 是多少,用 XY X − Y 更新 ans a n s 即可。

时间复杂度:枚举是 O(N) O ( N ) 的,每次枚举中查找可能值+排序是 O(NNlogN) O ( N + N log ⁡ N ) 的,所以总复杂度是 O(N2logN) O ( N 2 log ⁡ N )


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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值