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 }

 

转载于:https://www.cnblogs.com/yutingmoran/p/5901567.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值