L3-2. 堆栈(线段树单点更新)

来源:互联网 发布:神马快递打印软件 编辑:程序博客网 时间:2024/05/20 09:23

题目链接:https://www.patest.cn/contests/gplt/L3-2

思路分析:本题可以用一句话描述,就是求堆栈的中位数。堆栈是可以用数组模拟实现,可以用一个栈顶和栈底指针来实现数组模拟堆栈,分别用top和bottom。初始时,top=0,bottom=0,出栈的时候bottom++,进栈的时候top++。可以发现,栈中的所有元素恰好对应到数组里一段下标连续的子数组中。那么原问题就可以转化成求数组的中位数了,问题想到这里就很容易解决了,中位数即第n/2大的数,故可以用区间第K大的算法解决,但是这里出栈入栈涉及到更新,并非一般的静态区间第K大(只有询问没有修改的区间第K大),而是动态区间第K大。然后套用模板解决之。

细想之后,总感觉用区间第K大解决这个问题有点大材小用了,结合题目所给数据大小的限定,由于所给的数是0~10^5之间的数,而且查的又是整个区间的第n/2大的数,那么可以考虑建一棵维护区间里的数出现的次数的线段树。例如,区间[1,10]维护的是1,2,3,4,5,6,7,8,910总共出现多少次。

那么利用线段树单点更新即可实现维护。而查找中位数时只需要在线段树中找到第n/2大的数所在的叶子节点,叶子节点所对应的区间(叶子节点的区间l=r)值即为中位数。

AC代码:

#include<iostream>#include<stack>#include<algorithm>#include<cstdio>#include<cstring>#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1using namespace std;const int maxn=100002;int sum[maxn<<2];void pushUp(int rt){    sum[rt]=sum[rt<<1]+sum[rt<<1|1];}void build(int l,int r,int rt){    if(l==r)    {        sum[rt]=0;        return ;    }    int m=(l+r)>>1;    //printf("l = %d r = %d root = %d\n",l,r,rt);    build(lson);    build(rson);    pushUp(rt);}void update(int l,int r,int rt,int p,int v){    if(l==r)    {        if(v==0) sum[rt]--;        else sum[rt]++;        return ;    }    int m=(l+r)>>1;    if(p<=m) update(lson,p,v);    else update(rson,p,v);    pushUp(rt);}int query(int l,int r,int rt,int num){    if(l==r) return l;    int m=(l+r)>>1;    if(sum[rt<<1]>=num) return query(lson,num);    return query(rson,num-sum[rt<<1]);}void debug(){    printf("debug\n");}int main(){    //debug();    //freopen("in.txt","r",stdin);    int t;    build(1,maxn,1);    //debug();    scanf("%d",&t);    //cout<<t<<endl;    stack<int>st;    while(t--)    {        char buf[20];        scanf("%s",buf);        if(buf[1]=='o')        {            if(st.size())            {                printf("%d\n",st.top());                update(1,maxn,1,st.top(),0);                st.pop();            }            else puts("Invalid");        }        else if(buf[1]=='u')        {            int x;            scanf("%d",&x);            st.push(x);            update(1,maxn,1,x,1);        }        else        {            int cnt=st.size();            if(!cnt)            {                puts("Invalid");                continue;            }            if(cnt&1) cnt++;            printf("%d\n",query(1,maxn,1,cnt>>1));        }    }    return 0;}


0 0
原创粉丝点击