2017.10.7 国庆清北 D7T2 第k大区间
题目描述
定义一个长度为奇数的区间的值为其所包含的的元素的中位数。
现给出n个数,求将所有长度为奇数的区间的值排序后,第K大的值为多少。
输入输出格式
输入格式:
输入文件名为kth.in。
第一行两个数n和k
第二行,n个数。(0<=每个数<2^31)
输出格式:
一个数表示答案
输入输出样例
输入样例#1:
4 3 3 1 2 4 【样例解释】 [l,r]表示区间l~r的值 [1,1]:3 [2,2]:1 [3,3]:2 [4,4]:4 [1,3]:2 [2,4]:2
输出样例#1:
2
说明
对于30%的数据,1<=n<=100;
对于60%的数据,1<=n<=300
对于80%的数据,1<=n<=1000
对于100%的数据,1<=n<=100000, k<=奇数区间的数
1 /* 2 二分答案t,统计中位数大于等于t的区间有多少个。 3 设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)。 4 设b[i]=a[i]*2-i,统计每个b[i]有多少个b[j]<b[i](j<i 且 j和i奇偶性不同) 5 */ 6 7 #include<iostream> 8 #include<cstdio> 9 #include<cstring> 10 #include<algorithm> 11 #include<cmath> 12 #define N 100005 13 using namespace std; 14 15 long long n,k,ans; 16 int a[N],b[N],c[N],f[2][N*3]; 17 18 inline int lowbit(int x) 19 { 20 return x&-x; 21 } 22 23 inline void add(int x,int p) 24 { 25 if(x<=0) return; 26 for(;x<=3*n;x+=lowbit(x)) f[p][x]++; 27 } 28 29 inline int query(int x,int p) 30 { 31 if(x<=0) return 0; 32 int sum=0; 33 for(;x;x-=lowbit(x)) sum+=f[p][x]; 34 return sum; 35 } 36 37 long long check(int x) 38 { 39 memset(f,0,sizeof(f)); 40 long long sum=0; 41 for(int i=1;i<=n;i++) 42 { 43 c[i]=c[i-1]+(a[i]>=x); 44 } 45 for(int i=1;i<=n;i++) 46 { 47 c[i]=c[i]*2-i+n; 48 } 49 add(n,0); 50 for(int i=1;i<=n;i++) 51 { 52 add(c[i],i&1); 53 sum+=query(c[i]-1,(i+1)&1); 54 } 55 return sum; 56 } 57 58 inline void init() 59 { 60 scanf("%lld%lld",&n,&k); 61 for(int i=1;i<=n;i++) 62 { 63 scanf("%d",&a[i]); 64 b[i]=a[i]; 65 } 66 sort(b+1,b+n+1); 67 int l=1,r=n+1,mid=(l+r)>>1; 68 while(l+1<r) 69 { 70 if(check(b[mid])>=k) l=mid; 71 else r=mid; 72 mid=(l+r)>>1; 73 } 74 printf("%d",b[l]); 75 } 76 77 int main() 78 { 79 init(); 80 fclose(stdin);fclose(stdout); 81 return 0; 82 }