树状数组--csu 1933

来源:互联网 发布:java集合框架详解 编辑:程序博客网 时间:2024/05/16 00:27

1933: 购买饮料


小明家门口有一个卖饮料的自动售货机,小明经常在那里买饮料。
每种饮料有一个流行度,表示它在市场上流行的程度,为了显示自己的与众不同,小明从来不买流行度大于t的饮料。
售货机上有三种操作:
1 在货架上添加一种流行度为x的饮料,并以j作为该饮料的编号,j表示该饮料是第j个被添加的饮料(j从1开始计数)。
2 编号为x的饮料已售罄。
3 小明尝试买第x流行的饮料。

Input

第一行一个整数t。
接下来若干行每行两个整数i,x。1<=i<=3 表示该操作是第i种操作。
输入以只包含一个整数0的一行结束。
0<t,x<=106

Output

对每个i=3的操作:
如果小明尝试买的饮料流行度v>t,输出"Sorry.";
如果小明尝试买的饮料流行度v<=t,并且未售罄,输出该饮料的流行度;
如果小明尝试购买的饮料已卖完,输出"Meiyou.".
每个输出占一行。

Sample Input

991 1003 11 991 991 992 42 23 20

Sample Output

Sorry.99

树状数组加二分的模板,首先,树状数组C[i]存储的是A[i-2^k+1]至A[i]的和,通过树状数组我们可以在log(n)时间内轻松求数组的前缀和和子段和,考虑到这种情况,数组的前缀和一定是非递减的,所以可以使用二分,我们只要将拥有的流行度的饮料建成一个树状数组通过求前缀和来确定前面有多少种类饮料,二分时候,假设我们要求第i流行的饮料,最后二分到第一个sum(前缀和)等于第i流行的饮料即可,二分区间为【left,right)左闭右开,所以二分时right=mid。

#include <iostream>#include <stdio.h>#include <string.h>#define siz 1000005#include <queue>using namespace std;int arr[siz],t,i,inde,SSum;int vis[siz],C[siz],A[siz];int lowbit(int x){return x&-x;}void Insert(int index,int x){        A[index]=x;vis[x]++;        if(vis[x]<=1){           // cout<<x<<" !!!!!!!!!!!!!!!!!"<<endl;            while(x<siz){            C[x]+=1;            x+=lowbit(x);        }        ++SSum;        }}int Sum(int index){    int sum=0;    while(index>0){        sum+=C[index];        index-=lowbit(index);    }    return sum;}int erfen(int zx){    int left=1,right=siz;    int mid;    while(left<right){        mid=(left+right)>>1;   // cout<<left<<" "<<right<<" "<<mid<<" "<<Sum(mid)<<" "<<zx<<endl;        if(Sum(mid)<zx) left=mid+1;        else if(Sum(mid)>=zx) right=mid;    }    //cout<<Sum(mid)<<"&&"<<mid<<endl;    return left;}void New(int x){    int d=A[x];    vis[d]--;}void query(int x){    //cout<<SSum<<"%%%%%%%%%%%%%%%%"<<endl;    int zx=SSum-x+1;    int ans=erfen(zx);    //cout<<ans<<endl;    if(ans>t){       // cout<<"Sorry."<<endl;       printf("Sorry.\n");    }    else{        if(vis[ans]<=0) //cout<<"Meiyou."<<endl;            printf("Meiyou.\n");        else        printf("%d\n",ans);        //cout<<ans<<endl;    }}int main(){    scanf("%d",&t);    inde=0;    int x;    //right=1;    while(1){        scanf("%d",&i);        if(!i) break;        scanf("%d",&x);        if(i==1){            Insert(++inde,x);            //++index;        }        else if(i==2){            New(x);        }        else{            query(x);        }    }    return 0;}



原创粉丝点击