D. Med-imize

D. Med-imize

Given two positive integers n and k, and another array a of n integers.

In one operation, you can select any subarray of size k of a, then remove it from the array without changing the order of other elements. More formally, let (l,r) be an operation on subarray al,al+1,,ar such that rl+1=k, then performing this operation means replacing a with [a1,,al1,ar+1,,an].

For example, if a=[1,2,3,4,5] and we perform operation (3,5) on this array, it will become a=[1,2]. Moreover, operation (2,4) results in a=[1,5], and operation (1,3) results in a=[4,5].

You have to repeat the operation while the length of a is greater than k (which means |a|>k). What is the largest possible median of all remaining elements of the array a after the process?

The median of an array of length n is the element whose index is (n+1)/2 after we sort the elements in non-decreasing order. For example: median([2,1,5,4,3])=3, median([5])=5, and median([6,8,2,4])=4.

Input

The first line contains a single integer t (1t104) — the number of test cases.

The first line of each test case contains two integers n and k (1n,k5105).

The second line contains n integers a1,a2,,an (1ai109) — the array a.

It is guaranteed that the sum of n over all test cases does not exceed 5105.

Output

For each test case, print a single integer — the largest median possible after performing the operations.

Example

Input

5
4 3
3 9 9 2
5 3
3 2 5 6 4
7 1
5 9 2 6 5 4 6
8 2
7 1 2 6 8 3 4 5
4 5
3 4 5 6

Output

3
4
9
6
4

Note

In the first test case, you can select a subarray (l,r) which can be either (1,3) or (2,4). Thus, two obtainable final arrays are [3] and [2]. The former one has the larger median (3>2) so the answer is 3.

In the second test case, three obtainable final arrays are [6,4], [3,4], and [3,2]. Their medians are 4, 3, and 2 respectively. The answer is 4.

In the third test case, only one element is left in the final array and it can be any element of the initial array. The largest one among them is 9, so the answer is 9.

 

解题思路

  好久没做过中位数的题了,结果赛时罚坐了一个多小时都没做出来。卡了很久才想到可以二分,但把小于二分值的 ai 设成了 0,其余设成 1,然后就是贪心找一定数量的 01 结果死活过不了。看题解才知道应该把小于二分值的 ai 设成 1,并且选出来的下标在模 k 意义下是是依次加 1 的,有了这些提示就会做了,真是菜到炸了。

  题目可以转换成选出 ((n1)modk)+1 个数(下面记为 m),假设对应的下标为 i0,im1,相邻两个下标之间需要间隔 ck(c0) 个元素,即 ij+1ij=ck+1

  对于涉及中位数的题可以考虑二分,对于二分值 mid,如果 aimid 则设为 wi=1,否则设为 wi=1。这样如果选出的 m 个数的中位数大于等于 mid,那么对应的 wi 的和必定大于 0。因此选出的 m 个数对应的 wi 的和应该尽可能大,此时可以考虑 dp了。

  选择的下标之间满足什么样的关系呢?可以知道选出的第一个数的下标 i0 必定满足 i0modk=0,并且由于 i1i0=ck+1,因此有 i1modk=1。进而发现对于选出的每个下标都有 ijmodk=j

  定义 f(i) 表示在前 i 个数中选择了 (imodk)+1 个数,且 ai 作为第 (imodk)+1 个数,关于 wi 的和的最大值,状态转移方程为 {f(i)=wi,imodk=0f(i)=maxj<ijmodk=(imodk)1{f(j)}+wi,imodk>0

  可以用一个 g(j)=maximodk=j{f(i)} 记录前缀最大值来加速转移。

  最后答案就是 maximodk=m1{f(i)}=g(m1)

  AC 代码如下,时间复杂度为 O(nlogA)

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N = 5e5 + 5;

int n, m;
int a[N];
int f[N], g[N];

bool check(int mid) {
    memset(g, -0x3f, (n - 1) % m + 1 << 2);
    for (int i = 0; i < n; i++) {
        int w = a[i] >= mid ? 1 : -1;
        if (i % m == 0) f[i] = w;
        else f[i] = g[i % m - 1] + w;
        g[i % m] = max(g[i % m], f[i]);
    }
    return g[(n - 1) % m] > 0;
}

void solve() {
    cin >> n >> m;
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }
    int l = 1, r = *max_element(a, a + n);
    while (l < r) {
        int mid = l + r + 1 >> 1;
        if (check(mid)) l = mid;
        else r = mid - 1;
    }
    cout << l << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
    
    return 0;
}

 

参考资料

  Editorial of Codeforces Round 963 (Div. 2):https://codeforces.com/blog/entry/132185

posted @   onlyblues  阅读(54)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!
历史上的今天:
2022-08-05 耍杂技的牛
Web Analytics
点击右上角即可分享
微信分享提示