您的位置:首页 > 其它

51nod 1686 第k大区间

2016-04-05 16:41 246 查看
1686 第K大区间


基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题


 收藏


 关注

定义一个区间的值为其众数出现的次数

现给出n个数,求将所有区间的值排序后,第K大的值为多少。

众数(统计学/数学名词)_百度百科 

Input
第一行两个数n和k(1<=n<=100000,k<=n*(n-1)/2)
第二行n个数,0<=每个数<2^31


Output

一个数表示答案。

首先想到二分答案,然后在o(n)或者o(nlogn)的复杂度里面判断比二分的X大的有多少个,

这道题学到的重要的思维是枚举区间右端点R,然后动态更新最大的L,那么就可以判断有L个区间符合,这样统计就不会漏掉。这里我的做法比较笨,复杂度应该是o(nlogn^2),用了map瞎搞,明显不是一个好的解法,主要学习枚举R的思维方式。继续努力吧蒟蒻。。。

#include <iostream>
#include <unordered_map>
#include <vector>
#include <cstdio>
using namespace std;
int n;
long long k;
unordered_map<int,int> hashs;
vector<int> v[100005];
const int maxn=100005;
struct po{
int r,l;
};

int arr[maxn];
int cnt[maxn];
long long cal(int x){
long long ret=0;
vector<po> pa;
for(int i=0;i<n;i++){
if(cnt[i]>=x){
int l=v[hashs[arr[i]]][cnt[i]-x];
po p;
p.l=l;
p.r=i;
pa.push_back(p);
}
}
int add=0;
for(int i=0,j=0;i<n;i++){
if(j<pa.size()){
if(j+1<pa.size()&&i>=pa[j+1].r){
j++;
}
if(i>=pa[j].r){
add=max(add,pa[j].l+1);
ret+=add;
}

}
}
return ret;
}

int bs(int a,int b,long long val){
int low=a,high=b;
int ret=0;
while(low<=high){
int mid=(low+high)/2;
ret=mid;
long long x=cal(mid);
if(x==val)
break;
else if(x<val){
high=mid-1;
}
else{
low=mid+1;
}
}
long long x1=cal(ret);
if(x1==val){
return ret;
}
else if(x1<val){
return ret-1;
}
else if(x1>val){
return ret;
}
}

int main()
{
cin>>n>>k;
for(int i=0;i<n;i++){
scanf("%d",&arr[i]);
hashs[arr[i]]++;
cnt[i]=hashs[arr[i]];
}
unordered_map<int,int>::iterator it=hashs.begin();
for(int i=0;it!=hashs.end();i++,it++){
it->second=i;
}
for(int i=0;i<n;i++){
v[hashs[arr[i]]].push_back(i);
}
cout<<bs(1,n,k)<<endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: