51NOD 1686 第K大区间-----------------------思维(二分+双指针+套路题)

28 篇文章 0 订阅

在这里插入图片描述
解析:
套路! 套路! 套路! 一定要谨记!!!!!!!!

(套路)将求 k 大值大于等于 m 转化为求值大于等于 m 的数的数量大于等于 k。

套路二分枚举答案t。二分check的条件就是判断有多少个区间的众数>t

对于check的判断我详细说明一下(利用双指针) 先枚举右端点
假设有个序列: 1 2 3 1 4 3
假设二分的t=1;
那么对于[1,4]区间的众数是num[1]=2 那么有多少个区间满足num[1]=2呢?(这边的套路就要开始了)

我们发现[1,5],[1,6]都满足条件,所以当区间的众数>t 则产生的贡献就是n-i+1

然后我们需要移动左端点,每移动一位区间的众数-1 即可。
最终判断>t的区间个数sum
如果sum>=k 说明二分的t小了,需要调整下限
如果sum<k 说明二分的t大了,需要调整上限

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+1000;
ll a[N],b[N];
ll cnt[N];
int n,k;
bool check(int x)
{
  memset(cnt,0,sizeof cnt);
  ll ans=0;
  for(int i=1,l=1;i<=n;i++)
  {
    cnt[a[i]]++;
    while(cnt[a[i]]>x)
    {
      ans+=n-i+1;
      cnt[a[l]]--;
      l++;
    }

  }
  if(ans>=k) return   true;
  return false;
}
int main()
{
  scanf("%d %d",&n,&k);
  for(int i=1;i<=n;i++)
  {
    scanf("%lld",&a[i]);
    b[i]=a[i];
  }
  sort(b+1,b+1+n);
  int m=unique(b+1,b+1+n)-b-1;
  for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+1+m,a[i])-b;
  int l=1,r=n;
  int ans=0;
  while(l<=r)
  {
    int mid=l+r>>1;
    if(check(mid)) l=mid+1;
    else r=mid-1,ans=mid;
  }
  printf("%d\n",ans);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值