Codeforces Round 690 (Div3)

E Close Tuples

This is the hard version of this problem. The only difference between the easy and hard versions is the constraints on 𝑘 and 𝑚. In this version of the problem, you need to output the answer by modulo 10^9+7.

You are given a sequence 𝑎 of length 𝑛 consisting of integers from 1 to 𝑛. The sequence may contain duplicates (i.e. some elements can be equal).

Find the number of tuples of 𝑚 elements such that the maximum number in the tuple differs from the minimum by no more than 𝑘. Formally, you need to find the number of tuples of 𝑚 indices 𝑖1<𝑖2<…<𝑖𝑚, such that
m a x ( a i 1 , a i 2 , ⋯   , a i m ) − m i n ( a i 1 , a i 2 , ⋯   , a i m ) ≤ k max(a_{i1},a_{i2},\cdots,a_{im}) - min(a_{i1},a_{i2},\cdots,a_{im}) \leq k max(ai1,ai2,,aim)min(ai1,ai2,,aim)k

For example, if 𝑛=4, 𝑚=3, 𝑘=2, 𝑎=[1,2,4,3], then there are two such triples (𝑖=1,𝑗=2,𝑧=4 and 𝑖=2,𝑗=3,𝑧=4). If 𝑛=4, 𝑚=2, 𝑘=1, 𝑎=[1,1,1,1], then all six possible pairs are suitable.

As the result can be very large, you should print the value modulo 10^9+7 .

Input
The first line contains a single integer 𝑡 (1≤𝑡≤2⋅10^5) — the number of test cases. Then 𝑡 test cases follow.

The first line of each test case contains three integers 𝑛, 𝑚, 𝑘 (1≤𝑛≤2⋅10^5, 1≤𝑚≤100, 1≤𝑘≤𝑛) — the length of the sequence 𝑎, number of elements in the tuples and the maximum difference of elements in the tuple.

The next line contains 𝑛 integers 𝑎1,𝑎2,…,𝑎𝑛 (1≤𝑎𝑖≤𝑛) — the sequence 𝑎.

It is guaranteed that the sum of 𝑛 for all test cases does not exceed 2⋅10^5.

Output
Output 𝑡 answers to the given test cases. Each answer is the required number of tuples of 𝑚 elements modulo 10^9+7, such that the maximum value in the tuple differs from the minimum by no more than 𝑘.

Example

Input :

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

Output :

2
6
1
20

这是Round 690 Div3的E题,E题有easy 和 hard版本,这是hard版本。题目的大概意思是,给一个a序列,选m个数,使得这m个数的极差(最大值减最小值)不超过k,有多少种?(模上1e9 + 7)。

我的天,这么简单的题我比赛居然没做出来。很显然顺序不影响结果,所以先排序。然后可以感觉到这是一个滑动窗口问题,对于一个l,a[r]必须要小于等于a[l] + k。 但不知道比赛的时候脑子中了什么邪,我一直在想对数进行滑动窗口而非下标,在那边想确定头尾,怎么算中间m-2个数。不过有一说一这还真的算的出来,不过还真挺复杂。。

其实根本不需要确定头尾。为了防止重复,只需要确定一个头就可以了。确定一个l,找到r的边界,只需要在[l + 1, r]里选m-1个数,就不会重复了。 至于选下来有多少种,预处理一下组合数。

真的不知道自己在干嘛。。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>

using namespace std;
int t, n, m, k;
int mod = 1e9 + 7;
int a[200010];
long long c[200010][110];
void computeC() {
    c[0][0] = 1;
    for (int i = 1; i <= 200000; i++) {
        c[i][0] = 1;
        if (i <= 100) c[i][i] = 1;
    }
    for (int i = 2; i <= 200000; i++) {
        for (int j = 1; j <= min(i - 1, 100); j++) {
            c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;
        }
    }
}

int main()
{
    computeC();
    cin >> t;
    while (t--) {
        cin >> n >> m >> k;
        for (int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
        }
        sort(a + 1, a + n + 1);
        long long res = 0;
        int r = 1;
        for (int l = 1; l <= n; l++) {
            while (r + 1 <= n && a[r + 1] <= a[l] + k) r++;
            res = (res + c[r - l][m - 1]) % mod;
        }
        cout << res << endl;
    }
}

F The Treasure of The Segments

Polycarp found 𝑛 segments on the street. A segment with the index 𝑖 is described by two integers 𝑙𝑖 and 𝑟𝑖 — coordinates of the beginning and end of the segment, respectively. Polycarp realized that he didn’t need all the segments, so he wanted to delete some of them.

Polycarp believes that a set of 𝑘 segments is good if there is a segment [𝑙𝑖,𝑟𝑖] (1≤𝑖≤𝑘) from the set, such that it intersects every segment from the set (the intersection must be a point or segment). For example, a set of 3 segments [[1,4],[2,3],[3,6]] is good, since the segment [2,3] intersects each segment from the set. Set of 4 segments [[1,2],[2,3],[3,5],[4,5]] is not good.

Polycarp wonders, what is the minimum number of segments he has to delete so that the remaining segments form a good set?

Input
The first line contains a single integer 𝑡 (1≤𝑡≤2⋅10^5) — number of test cases. Then 𝑡 test cases follow.

The first line of each test case contains a single integer 𝑛 (1≤𝑛≤2⋅10^5) — the number of segments. This is followed by 𝑛 lines describing the segments.

Each segment is described by two integers 𝑙 and 𝑟 (1≤𝑙≤𝑟≤10^9) — coordinates of the beginning and end of the segment, respectively.

It is guaranteed that the sum of 𝑛 for all test cases does not exceed 2⋅10^5.

Output
For each test case, output a single integer — the minimum number of segments that need to be deleted in order for the set of remaining segments to become good.

Example
Input :

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

Output :

0
1
2
0

题目的意思也很简单。给n个闭区间,问最少需要删除几个区间,使得剩下的区间中,存在一个区间和其他所有区间都相交?(闭区间的端点相交也算相交)。

没来得及看这题,但其实也不难。我们遍历那个 “good” 区间,比如说是[x, y],显然我们需要删除所有右端点小于x的区间,以及所有左端点大于y的区间。题目显然复杂度不能超过 O ( n 2 ) O(n^2) O(n2),所以这个统计删除区间的过程需要在 log ⁡ n \log n logn复杂度,自然想到二分。所以把所有左端点存在一个数组ls里,右端点也一样。每次二分查找一下数目就行了,update一下需要删除的最小值。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>

using namespace std;
int t, n, m, k;
pair<int, int> segs[200010];
int ls[200010], rs[200010];

int main()
{
    cin >> t;
    while (t--) {
        cin >> n;
        for (int i = 1; i <= n; i++) {
            int l, r;
            scanf("%d %d", &l, &r);
            segs[i] = make_pair(l, r);
            ls[i] = l;
            rs[i] = r;
        }
        sort(ls + 1, ls + n + 1);
        sort(rs + 1, rs + n + 1);
        int res = n - 1;
        for (int i = 1; i <= n; i++) {
            int dl = lower_bound(rs + 1, rs + n + 1, segs[i].first) - (rs + 1);
            int dr = ls + n + 1 - upper_bound(ls + 1, ls + n + 1, segs[i].second);
            res = min(res, dl + dr);
        }
        cout << res << endl;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值