链接:https://www.nowcoder.com/acm/contest/102/C
来源:牛客网
We define a value of an interval is the second largest number of it's elements, and of course an interval has at least two elements. Given an array A with n elements and a number k, can you find the value of the kth largest interval?
输入描述:
The first line contains an integer number T, the number of test cases. For each test case : The first line contains two integer numbers n,k(2 ≤ n ≤ 105,1 ≤ k ≤ n(n−1)/2), the number of test cases. The second lines contains n integers Ai(1 ≤ Ai ≤ 109), the elements of array A.
输出描述:
For each test case print the value of the kth largest interval.
示例1
输入
2
3 3
1 2 3
5 1
1 2 2 3 3
输出
1
3
说明
For the sample input, there are three intervals.Interval [1 2 3] has value 2.Interval [2 3] has value 2.Interval [1 2] has value 1.So the 3rd largest interval is [1 2] whose value is 1.
题意: 设定一个区间的次小值,作为这个区间的权值,问所有的区间中,第k大的权值是多少?
分析:如果一个数是第k大的权值,就说明权值大于等于它的区间至少有k个。
枚举这样的一个数的时候,它的大小,和比它大的权值的数量呈线性关系,所以可以采用二分
当目前求大于等于x的权值个数的时候,区间包含两个大于等于x的数的时候才会产生贡献。
再通过尺取,求出不重复的贡献值总和。
代码如下:
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> #include <queue> using namespace std; typedef long long LL; const int MAXN=1e5+100; LL t,n,k; LL a[MAXN]; LL solve(LL x) { int last=0; LL num=0; int l,r; for(int i=1;i<=n;i++) if(a[i]>=x) { l=i; break; } r=l+1; while(r<=n) { if(a[r]>=x) { num+=(l-last)*(n-r+1); last=l; l=r; r=l+1; } else r++; } return num; } int main() { ios::sync_with_stdio(false); cin>>t; while(t--) { cin>>n>>k; for(int i=1;i<=n;i++) cin>>a[i]; LL l=1,r=1e9+1; while(l+1<r) { LL mid=(l+r)/2; if(solve(mid)>=k) l=mid; else r=mid; } cout<<l<<endl; } return 0; }