51nod1685 第K大区间2
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
1 #include<stdio.h> 2 #include<string.h> 3 #define MAXN 100000 + 10 4 #define INF (1<<30) - 1 + (1 << 30) 5 int a[MAXN]; 6 int jtree[2 * MAXN];//奇数 7 int otree[2 * MAXN];//偶数 8 int lowbit(int x) 9 { 10 return x & (-x); 11 } 12 void jAdd(int k) 13 { 14 while(k < 2 *MAXN) 15 { 16 jtree[k] ++; 17 k += lowbit(k); 18 } 19 } 20 21 22 int jSum(int k) 23 { 24 int sum = 0; 25 while(k) 26 { 27 sum += jtree[k]; 28 k -= lowbit(k); 29 } 30 return sum; 31 } 32 void oAdd(int k) 33 { 34 while(k < 2 *MAXN) 35 { 36 otree[k] ++; 37 k += lowbit(k); 38 } 39 } 40 41 42 int oSum(int k) 43 { 44 int sum = 0; 45 while(k) 46 { 47 sum += otree[k]; 48 k -= lowbit(k); 49 } 50 return sum; 51 } 52 int main() 53 { 54 int n; 55 long long k; 56 scanf("%d%lld",&n,&k); 57 for(int i = 0; i < n; i++) 58 scanf("%d",a+i); 59 long long l = 0,r = INF,mid; 60 while(l < r) 61 { 62 memset(jtree,0,sizeof(jtree)); 63 memset(otree,0,sizeof(otree)); 64 // jAdd(MAXN); 65 mid = (r + l + 1) / 2; 66 // printf("%d...\n",mid); 67 long long sum = 0,ans = 0; 68 for(int i = 0; i < n; i ++) 69 { 70 if(a[i] >= mid) 71 { 72 sum ++; 73 } 74 else 75 sum--; 76 if(i % 2 == 0) 77 { 78 ans += jSum(sum + MAXN -1); 79 oAdd(sum + MAXN); 80 if(sum > 0) 81 ans ++; 82 } 83 else 84 { 85 ans += oSum(sum + MAXN - 1); 86 jAdd(sum + MAXN); 87 } 88 } 89 if(ans >= k) 90 l = mid; 91 else 92 r = mid - 1; 93 } 94 printf("%lld\n",l); 95 return 0; 96 }