码迷,mamicode.com
首页 > 编程语言 > 详细

PAT甲题题解-1057. Stack (30)-树状数组

时间:2017-04-25 23:35:06      阅读:268      评论:0      收藏:0      [点我收藏+]

标签:多少   sum   pen   memset   display   ret   建议   splay   amp   

不懂树状数组的童鞋,正好可以通过这道题学习一下树状数组~~百度有很多教程的,我就不赘述了


题意:有三种操作,分别是
1.Push key:将key压入stack
2.Pop:将栈顶元素取出栈
3.PeekMedian:返回stack中第(n+1)/2个小的数

建立一个栈来模拟push和pop,另外还需要树状数组,来统计栈中<=某个数的总个数
不了解树状数组的建议学习一下,很有用的。
树状数组为c,有个虚拟的a数组,a[i]表示i出现的次数
sum(i)就是统计a[1]~a[i]的和,即1~i出现的次数
当我要询问第k个数是多少时,那么我可以通过二分查找来找出第k个数
首先另l=min,r=max,这里min=1,max=100000,mid=(l+r)/2
如果k<=sum(mid),说明1~mid的总个数>=k,则第k个数肯定是在1~mid之间,所以r=mid
如果k>sum(mid),说明1~mid的总个数<k,则第k个数肯定是在mid~r之间,所以l=mid
最后到l与r相邻终止循环
此时如果sum(l)<k && k<=sum(r),说明第k个数即为多个r中的一个
否则的话,说明第k个数为多个l中的一个。

当执行push key的时候,update(key,1),即a[key]++,key出现的次数增加1
当执行pop的时候,update(key,-1),即a[key]--,key出现的次数减少1

 

技术分享
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string.h>
#include <map>
#include <set>
#include <stack>
using namespace std;
const int maxn=100000+5;
int n;
int c[maxn]; //树状数组
int lowbit(int x){
    return x&(-x);
}
//树状数组的单点更新操作
void update(int i,int val){
    while(i<maxn){
        c[i]+=val;
        i+=lowbit(i);
    }
}
//树状数组的区间求和操作
int sum(int i){
    int res=0;
    while(i){
        res+=c[i];
        i-=lowbit(i);
    }
    return res;
}

int query(int cnt){
    //二分查找哪个数是第cnt个大的
    int l=1,r=maxn-1;
    while(l<r-1){
        int mid=(l+r)>>1;
        //<=mid的数有sum(mid)个
        if(cnt<=sum(mid)){
            r=mid;
        }
        else{
            l=mid;
        }
    }
    if(sum(l)<cnt && cnt<=sum(r))
        return r;
    else
        return l;
}
void test(){
    int sizes=7;
    int a[7]={1,2,2,3,4,4,5};
    for(int i=0;i<sizes;i++){
        update(a[i],1);
    }
    int q;
    while(scanf("%d",&q)!=EOF){
        printf("%d\n",query(q));
    }
}
int main()
{
    char str[15];
    memset(c,0,sizeof(c));
    //test();
    scanf("%d",&n);
    stack<int>stacks;
    int cnt=0;
    int tmp;
    for(int i=0;i<n;i++){
        scanf("%s",str);
        if(str[1]==o){
            if(cnt==0)
                printf("Invalid\n");
            else{
                tmp=stacks.top();
                stacks.pop();
                cnt--;
                update(tmp,-1);
                printf("%d\n",tmp);
            }
        }
        else if(str[1]==u){
            scanf("%d",&tmp);
            stacks.push(tmp);
            cnt++;
            update(tmp,1);
            //printf("%d\n",tmp);
        }
        else{
            if(cnt==0)
                printf("Invalid\n");
            else{
                int idx=(cnt+1)/2;
                int ans=query(idx);
                printf("%d\n",ans);
            }
        }
    }
    return 0;
}
View Code

 

PAT甲题题解-1057. Stack (30)-树状数组

标签:多少   sum   pen   memset   display   ret   建议   splay   amp   

原文地址:http://www.cnblogs.com/chenxiwenruo/p/6765075.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!