码迷,mamicode.com
首页 > 其他好文 > 详细

hihocoder-1483区间价值 (二分+尺取法)

时间:2017-04-08 00:12:49      阅读:680      评论:0      收藏:0      [点我收藏+]

标签:amp   div   ble   n+1   coder   span   problem   class   blog   

题目链接:

区间价值

给定n个数A1...An,小Ho想了解AL..AR中有多少对元素值相同。小Ho把这个数目定义为区间[L,R]的价值,用v[L,R]表示。

例如1 1 1 2 2这五个数所组成的区间的价值为4。

现在小Ho想知道在所有的的v[L,R](1 <= L <= R <= n)中,第k小的值是多少。

Input

第一行一个数T(T<=10),表示数据组数。

对于每一组数据:

第一行两个数n,k(1<=n<=200,000,1<=k<=n*(n+1)/2)

第二行n个数A1…An(1<=Ai<=1,000,000,000)

Output

一个数表示答案。

Sample Input

2
4 7
1 1 2 3
3 6
100 100 100

Sample Output

0
3

题意:

思路:先离散化,然后二分答案,check的时候用尺取法取计算有多少个区间的价值<=mid,然后和k比较,复杂度为O(n*logn)

 代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=2e5+10;
int a[maxn],n,vis[maxn],num[maxn],tep[maxn];
LL k;
int check(LL x)
{
    int l=1;
    LL sum=0,ans=0;
    for(int i=1;i<=n;i++)vis[a[i]]=0;
    for(int i=1;i<=n;i++)
    {
        sum=sum+vis[a[i]];
        vis[a[i]]++;
        while(sum>x&&l<=i)
        {
            vis[a[l]]--;
            sum-=vis[a[l]];
            l++;
        }
        ans=ans+(i-l+1);
    }
    if(ans>=k)return 1;
    return 0;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%lld",&n,&k);
        int cnt=0;
        for(int i=1;i<=n;i++)scanf("%d",&a[i]),tep[i]=a[i];
        sort(tep+1,tep+n+1);
        for(int i=1;i<=n;i++)
        {
            if(tep[i]==tep[i-1])continue;
            else num[cnt++]=tep[i];
        }
        for(int i=1;i<=n;i++)a[i]=lower_bound(num,num+cnt,a[i])-num;
        LL l=0,r=(LL)(n-1)*n/2;
        while(l<=r)
        {
            LL mid=(l+r)>>1;
            if(check(mid))r=mid-1;
            else l=mid+1;
        }
        cout<<r+1<<endl;
    }
    return 0;
}

  

hihocoder-1483区间价值 (二分+尺取法)

标签:amp   div   ble   n+1   coder   span   problem   class   blog   

原文地址:http://www.cnblogs.com/zhangchengc919/p/6680604.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!