L3-002. 堆栈
题目链接:https://www.patest.cn/contests/gplt/L3-002
线段树
可以用一个数组a[i]维护栈内数字为i的个数,若[0,K]中有n/2个数,即有n/2个比K小的数,则K为中位数。
线段树的数据修改和查询都是O(lgn)的,此题只需维护各个区间内的数的个数即可。
代码如下:
1 #include<cstdio> 2 #include<algorithm> 3 #include<stack> 4 #define N 100001 5 #define lson l,m,n<<1 6 #define rson m+1,r,n<<1|1 7 using namespace std; 8 stack<int>pq; 9 int st[N<<2]; 10 void build(int l,int r,int n,int key); 11 void change(int l,int r,int n,int key); 12 void updata(int n); 13 int query(int l,int r,int n,int key); 14 int main(void){ 15 freopen("in.txt","r",stdin); 16 int n,key; 17 char s[15]; 18 scanf("%d",&n); 19 while(n--){ 20 scanf("%s",s); 21 switch(s[1]){ 22 case 'o': 23 if(pq.empty())printf("Invalid "); 24 else{ 25 key=pq.top(); 26 printf("%d ",key); 27 pq.pop(); 28 change(1,100000,1,key); 29 } 30 break; 31 case 'u': 32 scanf("%d",&key); 33 pq.push(key); 34 build(1,100000,1,key); 35 break; 36 case 'e': 37 if(pq.empty())printf("Invalid "); 38 else{ 39 key=pq.size()+1; 40 key>>=1; 41 printf("%d ",query(1,100000,1,key)); 42 } 43 break; 44 } 45 } 46 return 0; 47 } 48 void build(int l,int r,int n,int key){ 49 if(l>=r){ 50 st[n]++; 51 return; 52 } 53 int m=(l+r)/2; 54 if(key<=m)build(lson,key); 55 else build(rson,key); 56 updata(n); 57 } 58 void change(int l,int r,int n,int key){ 59 if(l==r){ 60 st[n]--; 61 return; 62 } 63 int m=(l+r)/2; 64 if(key<=m)change(lson,key); 65 else change(rson,key); 66 updata(n); 67 } 68 void updata(int n){ 69 st[n]=st[n<<1]+st[n<<1|1]; 70 } 71 int query(int l,int r,int n,int key){ 72 if(l==r)return l; 73 int m=(l+r)/2; 74 if(key<=st[n<<1])return query(lson,key); 75 else return query(rson,key-st[n<<1]); 76 }