51nod 第K大区间2(二分+树状数组)

时间:2024-05-13 11:38:02

题目链接:

第K大区间2

基准时间限制:1.5 秒 空间限制:131072 KB 分值: 160

定义一个长度为奇数的区间的值为其所包含的的元素的中位数。中位数_百度百科

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

样例解释:

[l,r]表示区间的值
[1]:3
[2]:1
[3]:2
[4]:4
[1,3]:2
[2,4]:2

第三大是2

Input
第一行两个数n和k(1<=n<=100000,k<=奇数区间的数量)
第二行n个数,0<=每个数<2^31
Output
一个数表示答案。
Input示例
4 3
3 1 2 4
Output示例
2

题意:

思路:

二分答案t,统计中位数大于等于t的区间有多少个。
设a[i]为前i个数中有a[i]个数>=t,若奇数区间[l,r]的中位数>=t,则(a[r]-a[l-1])*2>r-l+1,即(a[r]*2-r)>(a[l-1]*2-l+1)。
设b[i]=a[i]*2-i,统计每个b[i]有多少个b[j]<b[i](j<i 且 j和i奇偶性不同)
总复杂度O(nlognlogn)

AC代码:
//#include <bits/stdc++.h>
#include <vector>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <cstring>
#include <algorithm>
#include <cstdio> using namespace std;
#define Riep(n) for(int i=1;i<=n;i++)
#define Riop(n) for(int i=0;i<n;i++)
#define Rjep(n) for(int j=1;j<=n;j++)
#define Rjop(n) for(int j=0;j<n;j++)
#define mst(ss,b) memset(ss,b,sizeof(ss));
typedef long long LL;
template<class T> void read(T&num) {
char CH; bool F=false;
for(CH=getchar();CH<''||CH>'';F= CH=='-',CH=getchar());
for(num=;CH>=''&&CH<='';num=num*+CH-'',CH=getchar());
F && (num=-num);
}
int stk[], tp;
template<class T> inline void print(T p) {
if(!p) { puts(""); return; }
while(p) stk[++ tp] = p%, p/=;
while(tp) putchar(stk[tp--] + '');
putchar('\n');
} const LL mod=1e9+;
const double PI=acos(-1.0);
const LL inf=1e10;
const int N=1e5+; int n,k;
int a[N],b[N],sum[][N]; int lowbit(int x)
{
return x&(-x);
}
void update(int x,int flag)
{
while(x<=n)
{
sum[flag][x]++;
x+=lowbit(x);
}
}
int query(int x,int flag)
{
int s=;
while(x>)
{
s+=sum[flag][x];
x-=lowbit(x);
}
return s;
} struct node
{
int temp,pos,id;
}po[N];
int cmp1(node x,node y)
{
if(x.temp==y.temp)return x.pos<y.pos;
return x.temp<y.temp;
}
int cmp2(node x,node y)
{
return x.pos<y.pos;
}
int check(LL x)
{
mst(sum,);
Riep(n)
{
b[i]=b[i-]+(a[i]>=x?:);
po[i].temp=*b[i]-i;
po[i].pos=i;
}
sort(po+,po+n+,cmp1);
Riep(n)po[i].id=i;
sort(po+,po+n+,cmp2);
LL ans=;
Riep(n)
{
if(po[i].temp>&&i%==)ans++;//包括0的;
ans=ans+query(po[i].id,i&^);
update(po[i].id,i&);
}
if(ans>=k)return ;
return ;
} int main()
{
read(n);read(k);
Riep(n)read(a[i]);
LL l=,r=inf;
while(l<=r)
{
LL mid=(l+r)>>;
if(check(mid))l=mid+;
else r=mid-;
}
print(l-);
return ;
}