http://pat.zju.edu.cn/contests/pat-a-practise/1057
题目的意思是可以在一个可以任意添加于删除整数的集合里随时查找该集合的中位数
每次查找用nlogn的方法显然会超时
所以要一种方法接近0(N)的查找方法, ( 计算第k大的数会超时!!)
比如当前有1,4,7
则树状数组的sum结果会是 1,1,1,2,2,2,3
现在就变成了二分查找(3+1)/2 ,即2的最左端的位置
ps: 2分查找有两种形式 (有一种会出错)
int find(int value)// 1,2,3 { int mid,ll=1,rr=3; while(ll<=rr) { mid=(ll+rr)/2; if(value<=s[mid])rr=mid-1; else ll=mid+1; } return ll; }
这种查找1,2,3都不会出错
int find(int value)//1,2,3 { int mid,ll=1,rr=3; while(ll<rr-1) { mid=(ll+rr)/2; if(value<=s[mid])rr=mid; else ll=mid; } return rr; }
这种查找1是会出错!!!
#include<stdio.h> #include<string.h> #include<iostream> #include<stack> using namespace std; int n=100000; int tree[110009]; int add[110009]; int size=0; int lowbit(int x) { return x&(-x); } void updata(int x,int c) { int i; for(i=x;i<=n;i+=lowbit(i)) { tree[i]+=c; } } int getsum(int x) { int i; int temp=0; for(i=x;i>=1;i-=lowbit(i)) { temp+=tree[i]; } return temp; } int find() { int ll=0,rr=100000,mid=(ll+rr)/2; int sum; while(ll<=rr){ mid=(ll+rr)/2; sum=getsum(mid); if(sum< ((size+1)/2)) ll=mid+1; else if(sum> ((size+1)/2)) rr=mid-1; else if(sum == ((size+1)/2)) rr=mid-1; } return ll; } int main() { int t; scanf("%d",&t); int i,temp; char ss[99]; stack<int>sta; for(i=0;i<=n;i++){ tree[i]=0; add[i]=0; } for(i=1;i<=t;i++){ scanf("%s",ss); if(ss[2]=='p'){ if(size==0){ printf("Invalid "); }else{ printf("%d ",sta.top()); updata(sta.top(),-1); add[sta.top()]--; sta.pop(); size--; } } if(ss[2]=='s'){ scanf("%d",&temp); add[temp]++; sta.push(temp); updata(temp,1); size++; } if(ss[2]=='e'){ if(size==0){ printf("Invalid "); }else{ printf("%d ",find()); } } } return 0; }