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;
}
}