ZOJ3635 Cinema in Akiba

本文介绍如何使用树状数组解决一个关于座位分配的问题,包括题意解释、解题思路、代码实现和实例演示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3635


题意:有n个geek,每个人一张票,每个票号ai表示这个geek要坐在当前第ai个空座上,入座顺序亦为1到n。下面输入query,分别要求输出输入的那个编号的geek座位号。


题解:树状数组。开始时每个点均为1插入,表示每个座位都是空座。然后对于要求为ai的空座,二分查找满足sum(ans)==ai&&sum(ans-1)==ai-1即为答案。保存后查询时输出,同时删去ans上点。


#include <cstdio>
#include <cstring>
#include <cmath>
#include <map>
#include <set>
#include <vector>
#include <iostream>
#include <algorithm>
#include<string>
using namespace std;
//const double eps=1e-7;
//const double INF=1e50;
//const double pi=acos(-1);

#define N 50005
#define M 10000

int c[N],n,ans[N];

void add(int p,int d)//p位置上加d
{
    while(p<=n)
    {
        c[p]+=d;
        p+=p&(-p);//lowbit[i]=i&(-i);
    }
}

int sum(int p)//a[1]+...+a[p]
{
     int ret=0;
     while (p)
     {
         ret+=c[p];
         p-=p&(-p);
     }
     return ret;
}

int find_kth(int k)//log(n)复杂度
{
    int s=1,t=n,mid,s1,s2;
    while (s<=t)
    {
        mid=(s+t)/2;

        s1=sum(mid);
        s2=sum(mid-1);
        if (s1==k && s2==(k-1)) return mid;
        else if (s1<k) s=mid+1;
        else t=mid-1;
    }

    return mid;
}

int main()
{
    //freopen("a","r",stdin);

    int i,ai,an,m;
    while (scanf("%d",&n)!=EOF)
    {
        for (i=1;i<=n;i++) add(i,1);

        for (i=1;i<=n;i++)
        {
            scanf("%d",&ai);
            an=find_kth(ai);
            ans[i]=an;
            add(an,-1);
        }

        scanf("%d",&m);
        for (i=1;i<=m;i++)
        {
            scanf("%d",&an);
            if (i>1) printf(" %d",ans[an]);
            else printf("%d",ans[an]);
        }

        printf("\n");
    }

    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值