链接:http://hihocoder.com/problemset/problem/1483
题意:一个区间价值为区间中相同数的对数。。求第k大区间
思路:和51nod上一个第k大区间类似,二分答案,统计是不是第k大的时候通过枚举左端点来求答案。时间复杂度nlogn,注意要提前做离散化处理,不然nlognlogn无法通过。
代码:
#include <bits/stdc++.h>
using namespace std;
long long n;
long long k;
map<int,int> mp;
long long hashs[200005];
const int maxn=200005;
int arr[maxn];
int cnt[maxn];
long long cal(long long x){
long long ret=0;
memset(hashs,0,sizeof(hashs));
long long L=0,R=0,sum=0;
hashs[arr[0]]++;
for(int i=0;i<n;i++){
while(sum<x&&R<n){
R++;
if(R>=n) break;
sum+=hashs[arr[R]];
hashs[arr[R]]++;
}
if(sum>=x)
ret+=n-R;
hashs[arr[i]]--;
sum-=hashs[arr[i]];
}
return ret;
}
long long bs(long long a,long long b,long long val){
long long low=a,high=b;
long long ret=0;
while(low<=high){
long long mid=(low+high)/2;
if(cal(mid)<=val){
high=mid-1;
}
else{
low=mid+1;
}
}
return low-1;
}
int main(){
int t;
scanf("%d",&t);
while(t--){
mp.clear();
scanf("%d%d",&n,&k);
for(int i=0;i<n;i++){
scanf("%d",&arr[i]);
mp[arr[i]]=1;
}
int idx=0;
for(map<int,int>::iterator it=mp.begin();it!=mp.end();it++)
it->second=idx++;
for(int i=0;i<n;i++){
arr[i]=mp[arr[i]];
}
printf("%lld
",bs(0,n*(n-1)/2,n*(n+1)/2-k));
}
return 0;
}