首页 > 其他分享 >H. Sakurako's Test

H. Sakurako's Test

时间:2024-09-02 23:36:29浏览次数:3  
标签:le int Sakurako test each Test array

H. Sakurako's Test

Sakurako will soon take a test. The test can be described as an array of integers $n$ and a task on it:

Given an integer $x$, Sakurako can perform the following operation any number of times:

  • Choose an integer $i$ ($1\le i\le n$) such that $a_i\ge x$;
  • Change the value of $a_i$ to $a_i-x$.

Using this operation any number of times, she must find the minimum possible median$^{\text{∗}}$ of the array $a$.

Sakurako knows the array but does not know the integer $x$. Someone let it slip that one of the $q$ values of $x$ will be in the next test, so Sakurako is asking you what the answer is for each such $x$.

$^{\text{∗}}$The median of an array of length $n$ is the element that stands in the middle of the sorted array (at the $\frac{n+2}{2}$-th position for even $n$, and at the $\frac{n+1}{2}$-th for odd)

Input

The first line contains one integer $t$ ($1\le t\le 10^4$)  — the number of test cases.

The first line of each test case contains two integers $n$ and $q$ ($1\le n,q\le 10^5$)  — the number of elements in the array and the number of queries.

The second line of each test case contains $n$ integers $a_1, a_2, \dots, a_n$ ($1\le a_i\le n$)  — the elements of the array.

The following $q$ lines each contain one integer $x$ ($1\le x\le n$).

It is guaranteed that the sum of $n$ across all test cases does not exceed $10^5$. The same guarantee applies to the sum of $q$ across all test cases.

Output

For each test case, output $q$ integers  — the answer for each query.

Example

Input

2
5 5
1 2 3 4 5
1
2
3
4
5
6 3
1 2 6 4 1 3
2
1
5

Output

0 1 1 1 2 
1 0 2 

 

解题思路

  首先要知道当集合中的元素越小,那么集合中元素的中位数越小。因此我们应该让一个数尽可能减去 $x$,最后得到 $a_i := a_i \bmod x$。对于固定的 $x$,在执行操作后中位数就已经确定了,即第 $\lfloor \frac{n}{2} \rfloor + 1$ 小的数。但由于需要对每个 $a_i$ 模 $x$,直接暴力做的话时间复杂度是 $O(qn)$。

  不妨换个思虑,对于每个 $x$ 二分出最小的中位数(初始时二分的左右端点分别为 $0$ 和 $x-1$),假设二分点为 $m$,那么余数不超过 $m$ 的元素个数如果至少为 $\lfloor \frac{n}{2} \rfloor + 1$,则说明中位数小于等于 $m$。因此现在问题是如何快速求出模 $x$ 后不超过 $m$ 的元素数量。

  把每个元素看作是 $q \cdot x + r, \, (q \in \mathbb{N}, \, 0 \leq r <x)$ 的形式,因此满足模 $x$ 不超过 $m$ 的数可以表示成区间 $[k \cdot x, k \cdot x + m]$。由于 $a_i \leq n$,因此 $k \leq \lfloor \frac{n}{x} \rfloor$。枚举 $k$,累加值在 $[k \cdot x, k \cdot x + m]$ 内的元素数量(可以用权值前缀和作差得到),最后判断累加的值是否不小于 $\lfloor \frac{n}{2} \rfloor + 1$ 即可。

  利用调和级数的性质,我们直接预处理出 $x \in [1, n]$ 的答案。时间复杂度就是 $\sum\limits_{x=1}^{n}{\frac{n}{x} \cdot \log{x}} \leq n \log^2{n}$。最后 $O(1)$ 查询即可。

  AC 代码如下,时间复杂度为 $O(n \log^2{n})$:

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

typedef long long LL;

const int N = 1e5 + 5;

int n, m;
int s[N], ans[N];

bool check(int x, int m) {
    int cnt = 0;
    for (int i = 0; i <= n; i += x) {
        cnt += s[min(n, i + m)] - s[i - 1];
    }
    return cnt >= n / 2 + 1;
}

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

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

 

参考资料

  Codeforces Round 970 (Div. 3) Editorial:https://codeforces.com/blog/entry/133509

标签:le,int,Sakurako,test,each,Test,array
From: https://www.cnblogs.com/onlyblues/p/18393746

相关文章

  • pytest中用装饰器控制新增接口请求时间
    示例场景假设我们有一个提交数据的函数submit_data,我们希望在每次调用后等待一定的时间,以避免重复提交的问题。1.自动化提交接口的时候可以使用time.sleep()的方式这是最直接的方式,在函数调用后直接使用time.sleep()控制等待时间。importtimedefsubmit_data(da......
  • pycharm警告 :PytestConfigWarning: Unknown config option: makers
    一、PytestConfigWarning:Unknownconfigoption:makers虽然不影响执行测试用例,但是,追求完美的我很想解决掉他! 二、找报错的单词在哪,大概率这种报错在ini文件我的makers在pytest.ini。起初是想打标签,但是标签的注解是@pytest.mark.xxx,所以就把makers改成了markers,果然没有......
  • 2022-2023 ICPC East Central North America Regional Contest (ECNA 2022):JL
    前言这场状态绝对不对劲,rk倒1没啥可说的。A.A-MazingPuzzle这题绝对能做!等我抽空回来补!(不挂在这的话,说不定就摆烂了)J.SimpleSolitaire题意英语阅读理解。自己读去。解法也不写了,纯暴力模拟。认罪认罚具结书好像是第一次当战犯吧。大约3个半小时的时候,我自告奋勇做这......
  • 2019-2020 ICPC Northwestern European Regional Programming Contest (NWERC 2019):GH
    前言目前打过的最逆天的一场,前半场CF评测机度假去了,全场Inqueue,两小时左右评测机终于回来了,Standings遍地开花,听取WA声一片。昨天就有好几道题是因为没及时看题所以没做,赛后还和队友商量说应该先把所有题大致看一遍,结果今天不长记性,还没看H和J,就去写思路不一定对+实现起来难得......
  • SDKD 2024 Summer Training Contest F2(The 13th Shandong ICPC Provincial Collegiat
    A-Orders题意每天能生产k个产品的工厂有n个订单,第i个订单是在a_i天交b_i个产品,问能否交付。思路订单按日期排序,记录剩下的商品.代码#define_CRT_SECURE_NO_WARNINGS#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongconstintmxn=1e6+5......
  • AtCoder Beginner Contest 369 补题记录
    A-369题意:给定A和B,求有多少个x可以和A,B构成等差数列思路:分三种情况讨论A==B则x不得不与A和B想等x位于A和B中间只有B-A为偶数才有这种情况存在x位于A和B两边可以在左边也可以在右边,只要A!=B这种情况总会存在voidsolve(){inta=read(),b=read();......
  • AtCoder Beginner Contest 368(ABC368)
    [ABC369C]CountArithmeticSubarrays题意:判断有多少个区间是等差数列(不能重排)。\(1\len\times10^5\)。思路:赛时看错题了,以为这个区间可以重排,卡了8min,小丑了。首先容易注意到,对于一个区间\([l,r]\),若其是等差数列,则这个区间的子区间\([l',r']\)肯定也是子序列,造成......
  • Atcoder Beginner Contest 369
    AtcoderBeginnerContest369C-CountArithmeticSubarrays题意给出一个长度为\(n\)的序列\(A\),求有多少个\(A\)的连续子序列为等差数列。思路对于递增的右端点,左端点不减。使用双指针,枚举右端点,扫描左端点。时间复杂度:\(O(n)\)。代码#include<bits/stdc++.h>usi......
  • AtCoder Beginner Contest 369 补题记录(A~G)
    AconstintN=1000100;inta[N];signedmain(){intx,y;cin>>x>>y;if(x==y)cout<<"1\n";elseif(x%2==y%2)cout<<"3\n";elsecout<<"2\n";}BconstintN=1000100;inta[N];sign......
  • AtCoder Beginner Contest 369 A~D
    封面原图画师かにょこAtCoderBeginnerContest369我愿称之为等差数列场A-369题意给两个数,问能和他们构成等差数列的数有多少个代码#include<bits/stdc++.h>#definemod998244353usingnamespacestd;typedeflonglongll;typedefdoubledb;type......