2018-12-04 pat5-4110丨二分丨树状数组

https://www.nowcoder.com/pat/5/problem/4110

题意

实现一个栈,在基础功能上,添加一个查找栈中位数的功能。(第(top+1)/2小的那个数)。

 

思路

一开始我想,由于插入的key不大,可以用一个频率数组num[i],记录小于等于i的栈元素有多少个,每次查找第一个大于等于(top+1)/2的num[i]就是所需要的。

但是呢,我觉得写二分不是我喜欢的。所以写了个暴力for莽了一遍,居然过了两个。

嗯,不过确实不应该逃避自己生疏的知识点。多思考一下确实会有新的收获,比如我今天对lower_bound有了更深的理解。

模拟一下发现,对查找一个存在的数,如果当前元素小于键值,left=mid+1,可以理解为,当前元素不会成为答案,就踢出搜索区间。如果当前元素大于等于键值,其实主要是等于键值的时候,right=mid,因为可能是答案之一,所以就不要把这个数踢出搜索区间。(精细一点应该分三类,偷懒的话就像我下面的写法,分两类就够了)

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 1e5+5;
const int INF = 0x3f3f3f3f;
int n;
int num[MAXN];
int stk[MAXN],top;
char op[25];

void add(int x,int val){
    while(x<MAXN){
        num[x]+=val;
        x+=x&-x;
    }
}

int ask(int x){
    int res=0;
    while(x){
        res+=num[x];
        x-=x&-x;
    }
    return res;
}

int bit(int x){
    int l=1,r=100000,m;
    while(l<r){
        m=(l+r)>>1;
        if(ask(m)<x) l=m+1;
        else r=m;//关键
    }
    return r;
}

int main(){
    scanf("%d",&n);

    for(int i=1,key;i<=n;i++){
        scanf("%s",op);
        if(op[1]=='o'){
            if(top){
                printf("%d\n",stk[top]);
                add(stk[top],-1);
                top--;
            }else puts("Invalid");
        }else if(op[1]=='e'){
            if(top) printf("%d\n",bit((top+1)/2));
            else puts("Invalid");
        }else{
            scanf("%d",&key);
            stk[++top]=key;
            add(stk[top],1);
        }
    }
    return 0;
}
/*
*/

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值