Poj 2828 Buy Tickets \ Zoj 3635 Cinema in Akiba

这两道题思路是一样的。

第一题:http://poj.org/problem?id=2828

题意:依次插入人,每个人插入的地方告知,求最终的排位。

乍看用链表来做即可,可是这样肯定会超时,不信试试:

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
using namespace std;

struct People
{
    int val;
    People() {}
    People(int _val)
    {
        val = _val;
        next = NULL;
    }
    People * next;
};

int size = 0;

int main()
{
#ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
#endif

    int n;
    int pos,val;
    int size = -1;
    while(scanf(" %d",&n)!=EOF)
    {
        People * head;
        People * last;
        head = last = new People(-1);
        size = 0;
        for(int i=0; i<n; i++)
        {
            scanf(" %d %d",&pos,&val);
            if(size <= pos)
            {
                last->next = new People(val);
                last = last->next;
            }
            else
            {
                People * temp = head;
                int count = 0;
                while(temp!=NULL)
                {
                    if(count == pos)
                    {
                        break;
                    }
                    temp = temp->next;
                    count++;
                }
                People * cur = temp->next;
                temp->next = new People(val);
                temp->next->next = cur;
            }
            size++;
        }
        People *temp = head->next;
        if(temp!=NULL)
        {

            while(temp->next!=NULL)
            {
                printf("%d ",temp->val);
                temp = temp->next;
            }
            printf("%d",temp->val);

        }
        printf("\n");
    }
    return 0;
}

其实我们可以这样想,题目中的数据是一次插入的。如果我们反过来思考,从后往前的话,最后一个人的位置肯定不发生变化,接下来,在最后一个人位置不发生变化的情况下,倒数第二个人的位置也不发生变化,一次类推。我们只要用线段树维护一个关于区间空位个数的数组即可。

#include <iostream>
#include <stdlib.h>
#include <stdio.h>

using namespace std;

#define Maxn 200005
#define lx (x<<1)
#define rx ((x<<1)|1)
#define MID ((l + r)>>1)

struct People
{
    int pos;
    int val;
};

People p[Maxn];

//维护空位
int S[Maxn<<2];
//最后的序列
int A[Maxn];

void pushUp(int x)
{
    S[x] = S[lx] + S[rx];
}
void build(int l,int r,int x)
{
    if(l == r)
    {
        S[x] = 1;
        return;
    }
    build(l,MID,lx);
    build(MID+1,r,rx);
    pushUp(x);
}
void update(int p,int d,int l,int r,int x)
{
    if(l == r)
    {
        S[x] = 0;
        A[l] = d;
        return;
    }
    if(p<S[lx]) update(p,d,l,MID,lx);
    else update(p-S[lx],d,MID+1,r,rx);
    pushUp(x);
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    #endif

    int n;
    while(scanf(" %d",&n)!=EOF)
    {
        for(int i=0;i<n;i++)
        {
            scanf(" %d %d",&p[i].pos,&p[i].val);
        }
        build(0,n-1,1);
        for(int i=n-1;i>=0;i--)
        {
            update(p[i].pos,p[i].val,0,n-1,1);
        }
        for(int i=0;i<n-1;i++)
        {
            printf("%d ",A[i]);
        }
        printf("%d\n",A[n-1]);
    }
    return 0;
}

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

这题是类似的,也是维护空位个数。

#include <iostream>
#include <stdlib.h>
#include <stdio.h>

using namespace std;

#define Maxn 50005
#define lx (x<<1)
#define rx ((x<<1)|1)
#define MID ((l + r)>>1)

int S[Maxn<<2];
int A[Maxn];
//排位
int rank[Maxn];

void pushUp(int x)
{
    S[x] = S[lx] + S[rx];
}
void build(int l,int r,int x)
{
    if(l == r)
    {
        S[x] = 1;
        return;
    }
    build(l,MID,lx);
    build(MID+1,r,rx);
    pushUp(x);
}
void update(int p,int d,int l,int r,int x)
{
    if(l == r)
    {
        S[x] = 0;
        A[l] = d;
        rank[d] = l;
        return;
    }
    if(p<S[lx]) update(p,d,l,MID,lx);
    else update(p-S[lx],d,MID+1,r,rx);
    pushUp(x);
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    #endif

    int n;
    int p;
    int q;
    while(scanf(" %d",&n)!=EOF)
    {
        build(1,n,1);
        for(int i=1;i<=n;i++)
        {
            scanf(" %d",&p);
            p--;
            update(p,i,1,n,1);
        }
        scanf(" %d",&q);
        for(int i=1;i<=q;i++)
        {
            scanf(" %d",&p);
            printf("%d",rank[p]);
            if(i!=q) printf(" ");
        }
        puts("");
    }
    return 0;
}


你可能感兴趣的:(Poj 2828 Buy Tickets \ Zoj 3635 Cinema in Akiba)