ZOJ 3635 Cinema in Akiba (树状数组+二分)

来源:互联网 发布:鲁尔山网络皇色视频免 编辑:程序博客网 时间:2024/06/05 15:38
//460ms#include<iostream>#include<cstdio>#include<cstring>#include<queue>using namespace std;#define low(x) x&(-x)int c[100005],ans[100005],n;void add(int i,int val){    while(i<=n)    {        c[i]+=val;        i+=low(i);    }}int getsum(int i){    int sum=0;    while(i>0)    {        sum+=c[i];        i-=low(i);    }    return sum;//getsum(i)表示该位置前(包括)还有多少空位}int main(){    int i;    while(scanf("%d",&n)!=EOF)    {        memset(c,0,sizeof(c));        memset(ans,0,sizeof(ans));        for(i=1;i<=n;i++)add(i,1);        for(i=1;i<=n;i++)        {            int mid,p;            scanf("%d",&p);            int r=n,l=1;            while(r>l)            {                mid=(r+l)/2;              //if(i==5)printf("===%d\n",mid);                if(getsum(mid)>=p)r=mid;//有重复值时向前找第一个                else l=mid+1;            }            ans[i]=r;            add(r,-1);            /*            一开始不是这样写的,wa到死!            错误代码:            while(l<=h)            {                int mid=(l+h)/2;                printf("mid=%d\n",mid);                if(p<getsum(mid)){                        h=mid-1;                }                else if(p>getsum(mid))l=mid+1;                else                {                    ans[i]=mid;                    add(mid,-1);                   // printf("--%d\n",mid);                    break;                }            }            */        }        int m;        scanf("%d",&m);;        while(m--)        {            int x;            scanf("%d",&x);            if(m)printf("%d ",ans[x]);            else printf("%d\n",ans[x]);        }    }    return 0;}

0 0