树状数组+二分答案查询第k大的数 (团体程序设计天梯赛 L3-002. 堆栈)
前提是数的范围较小
1 数据范围:O(n) 2 查第k大的数i:log(n)(树状数组查询小于等于i的数目)*log(n)(二分找到i) 3 添加:log(n) (树状数组) 4 删除:log(n) (树状数组)
团体程序设计天梯赛 L3-002. 堆栈
1 /*数据范围:O(n) 2 查第k大的数i:log(n)(树状数组查询小于等于i的数目)*log(n)(二分找到i) 3 添加:log(n) (树状数组) 4 删除:log(n) (树状数组) 5 */ 6 #include <cstdio> 7 #include <cstdlib> 8 #include <cmath> 9 #include <cstring> 10 #include <set> 11 #include <vector> 12 #include <stack> 13 #include <map> 14 #include <queue> 15 #include <algorithm> 16 #include <iostream> 17 using namespace std; 18 #define maxn 100000 19 20 long a[100005]; 21 long st[100005]; 22 23 int main() 24 { 25 long n,d,l,r,mid,i,g,c=0; 26 char s[20]; 27 for (i=0;i<=maxn;i++) 28 a[i]=0; 29 scanf("%ld",&n); 30 while (n) 31 { 32 n--; 33 scanf("%s",s); 34 if (strcmp(s,"Pop")==0) 35 { 36 if (c==0) 37 { 38 printf("Invalid\n"); 39 continue; 40 } 41 d=st[c]; 42 printf("%ld\n",d); 43 while (d<=maxn) 44 { 45 a[d]--; 46 d+=(d & (-d)); 47 } 48 c--; 49 } 50 else if (strcmp(s,"Push")==0) 51 { 52 scanf("%ld",&d); 53 c++; 54 st[c]=d; 55 while (d<=maxn) 56 { 57 a[d]++; 58 d+=(d & (-d)); 59 } 60 } 61 else 62 { 63 d=(c+1)>>1; 64 if (c==0) 65 { 66 printf("Invalid\n"); 67 continue; 68 } 69 l=1; r=maxn; 70 while (l<=r) 71 { 72 mid=(l+r)>>1; 73 g=0; 74 i=mid; 75 while (i>=1) 76 { 77 g+=a[i]; 78 i-=(i & (-i)); 79 } 80 if (g>=d) 81 r=mid-1; 82 else 83 l=mid+1; 84 } 85 printf("%ld\n",l); 86 } 87 } 88 return 0; 89 }