Description
定义一个长度为奇数的区间的值为其所包含的的元素的中位数。中位数_百度百科
现给出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
解题思路:(二分+树状数组)
区间第k大首先想到二分求中位数>=x的区间有多少个,所以快速求满足条件的区间才是关键,若大于等于x则1,否则 - 1;等到一个数组,求任意区间和>= 0 的奇数长度区间的个数即可,用两个数组数组分别维护区间和,在他前面和<=当前和的小标奇偶性不同的区间总个数,统计一下即可。
Code#include<stdio.h>
#include<string.h>
#define MAXN 100000 + 10
#define INF (1<<30) - 1 + (1 << 30)
int a[MAXN];
int jtree[2 * MAXN];//奇数
int otree[2 * MAXN];//偶数
int lowbit(int x)
{
return x & (-x);
}
void jAdd(int k)
{
while(k < 2 *MAXN)
{
jtree[k] ++;
k += lowbit(k);
}
}
int jSum(int k)
{
int sum = 0;
while(k)
{
sum += jtree[k];
k -= lowbit(k);
}
return sum;
}
void oAdd(int k)
{
while(k < 2 *MAXN)
{
otree[k] ++;
k += lowbit(k);
}
}
int oSum(int k)
{
int sum = 0;
while(k)
{
sum += otree[k];
k -= lowbit(k);
}
return sum;
}
int main()
{
int n;
long long k;
scanf("%d%lld",&n,&k);
for(int i = 0; i < n; i++)
scanf("%d",a+i);
long long l = 0,r = INF,mid;
while(l < r)
{
memset(jtree,0,sizeof(jtree));
memset(otree,0,sizeof(otree));
// jAdd(MAXN);
mid = (r + l + 1) / 2;
// printf("%d...\n",mid);
long long sum = 0,ans = 0;
for(int i = 0; i < n; i ++)
{
if(a[i] >= mid)
{
sum ++;
}
else
sum--;
if(i % 2 == 0)
{
ans += jSum(sum + MAXN -1);
oAdd(sum + MAXN);
if(sum > 0)
ans ++;
}
else
{
ans += oSum(sum + MAXN - 1);
jAdd(sum + MAXN);
}
}
if(ans >= k)
l = mid;
else
r = mid - 1;
}
printf("%lld\n",l);
return 0;
}
#include<stdio.h>
#include<string.h>
#define MAXN 100000 + 10
#define INF (1<<30) - 1 + (1 << 30)
int a[MAXN];
int jtree[2 * MAXN];//奇数
int otree[2 * MAXN];//偶数
int lowbit(int x)
{
return x & (-x);
}
void jAdd(int k)
{
while(k < 2 *MAXN)
{
jtree[k] ++;
k += lowbit(k);
}
}
int jSum(int k)
{
int sum = 0;
while(k)
{
sum += jtree[k];
k -= lowbit(k);
}
return sum;
}
void oAdd(int k)
{
while(k < 2 *MAXN)
{
otree[k] ++;
k += lowbit(k);
}
}
int oSum(int k)
{
int sum = 0;
while(k)
{
sum += otree[k];
k -= lowbit(k);
}
return sum;
}
int main()
{
int n;
long long k;
scanf("%d%lld",&n,&k);
for(int i = 0; i < n; i++)
scanf("%d",a+i);
long long l = 0,r = INF,mid;
while(l < r)
{
memset(jtree,0,sizeof(jtree));
memset(otree,0,sizeof(otree));
// jAdd(MAXN);
mid = (r + l + 1) / 2;
// printf("%d...\n",mid);
long long sum = 0,ans = 0;
for(int i = 0; i < n; i ++)
{
if(a[i] >= mid)
{
sum ++;
}
else
sum--;
if(i % 2 == 0)
{
ans += jSum(sum + MAXN -1);
oAdd(sum + MAXN);
if(sum > 0)
ans ++;
}
else
{
ans += oSum(sum + MAXN - 1);
jAdd(sum + MAXN);
}
}
if(ans >= k)
l = mid;
else
r = mid - 1;
}
printf("%lld\n",l);
return 0;
}