hihocoder 1483 区间价值(二分+双指针)

本文介绍了一种高效算法,用于查找所有区间中第k小的值,通过假设答案并使用双指针技术扫描区间,实现O(n)的时间复杂度。文章提供了完整的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

询问所有区间值中第k小的值,肯定不能把所有区间的值求出来,毕竟有n^2个区间。

我们如果先假设一个答案,然后能够找到所有区间里有多少个区间的值小于当前的答案的话,岂不是就可以二分答案了。那么如何去找到小于x的区间有多少个呢,如果你会双指针的话,这里用一下双指针就是再方便不过了,o(n)的扫一遍加上一个桶来统计区间里元素的值就好了。

然后由于元素的值的范围是0到1e9,所有要先离散化一下,然后就做完另外。


代码:

#include <bits/stdc++.h>
#define LL long long 
using namespace std;
const int maxn=2e5+5;
int a[maxn];
int b[maxn];
int ord[maxn];
int book[maxn];
int vis[maxn];
int n, k;
int check(LL x)
{
    int i, j, ed=0;
    LL sum=0, y, num=0;
    memset(book, 0, sizeof(book));
    book[ord[ed]]=1;
    for(i=0; i<n; i++)
    {
        while(ed<n && sum<=x)
        {
            ed++;
            y=book[ord[ed]];
            sum+=y;
            book[ord[ed]]++;
            
        }
    //    printf("%lld ed%d\n",  x, ed);
        num+=ed-i;
        book[ord[i]]--;
        sum-=book[ord[i]];
        
    }
    //printf("%lld %d\n", x, num);
    return num>=k;
}

int main()
{
    int t;
    cin>>t;   
    int i, j;
    while(t--)
    {
        scanf("%d%d", &n, &k);
    for(i=0; i<n; i++)
    {
        scanf("%d", &a[i]);
        b[i]=a[i];
    }
    sort(b, b+n);
    int len=unique(b, b+n)-b;
    for(i=0; i<n; i++)
    {
        ord[i]=lower_bound(b, b+len, a[i])-b;        
    }
//    for(i=0; i<n; i++)printf("%d ", ord[i]);printf("\n");

    LL l=0, r=n*(n+1)/2;
    LL mid;
    LL ans=0;
    for(i=0; i<100; i++)
    {
        mid=(l+r)>>1;
        if(check(mid))
        {
            ans=mid;
            r=mid-1;
        }
        else 
        {
            l=mid+1;
        }
        
    }
    printf("%lld\n", ans);
    }
    
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值