POJ2828Buy Tickets(线段树)

Buy Tickets
Time Limit: 4000MS Memory Limit: 65536K
Total Submissions: 17009 Accepted: 8423

Description

Railway tickets were difficult to buy around the Lunar New Year in China, so we must get up early and join a long queue…

The Lunar New Year was approaching, but unluckily the Little Cat still had schedules going here and there. Now, he had to travel by train to Mianyang, Sichuan Province for the winter camp selection of the national team of Olympiad in Informatics.

It was one o’clock a.m. and dark outside. Chill wind from the northwest did not scare off the people in the queue. The cold night gave the Little Cat a shiver. Why not find a problem to think about? That was none the less better than freezing to death!

People kept jumping the queue. Since it was too dark around, such moves would not be discovered even by the people adjacent to the queue-jumpers. “If every person in the queue is assigned an integral value and all the information about those who have jumped the queue and where they stand after queue-jumping is given, can I find out the final order of people in the queue?” Thought the Little Cat.

Input

There will be several test cases in the input. Each test case consists of N + 1 lines where N (1 ≤ N ≤ 200,000) is given in the first line of the test case. The next N lines contain the pairs of values Posi and Vali in the increasing order of i (1 ≤ i ≤ N). For each i, the ranges and meanings of Posi and Vali are as follows:

  • Posi ∈ [0, i − 1] — The i-th person came to the queue and stood right behind the Posi-th person in the queue. The booking office was considered the 0th person and the person at the front of the queue was considered the first person in the queue.
  • Vali ∈ [0, 32767] — The i-th person was assigned the value Vali.

There no blank lines between test cases. Proceed to the end of input.

Output

For each test cases, output a single line of space-separated integers which are the values of people in the order they stand in the queue.

Sample Input

4
0 77
1 51
1 33
2 69
4
0 20523
1 19243
1 3890
0 31492

Sample Output

77 33 69 51
31492 20523 3890 19243

Hint

The figure below shows how the Little Cat found out the final order of people in the queue described in the first test case of the sample input.


我发4,如果我没有对应线段树题目的练习的话,我是绝壁不会觉得这个题目是用线段树来解的,首先我们这里承诺,AC代码的这样的数据是不对的(本人表示题干读不懂)(英语渣)不知道有没有保证有这样的数据,但是我测试了的数据表示,这样的数据是题干不存在的:


这里表示一下题意:

黑天瞎火的买票排队,输入的数据表示来的人的顺序,第一个变量表示这个人(插队或不插队)到的位子,如果前边有这个位子的人直接推到后边去,表示题目中hint.写的很明白。因为来买票的不是傻逼,不会非得站到队列的最后边比如上边控制框(黄色)里边的数据。

然后我们就来解题啦~~~~~~

我们知道,最后来的人,站在的位子就是最终的位子,

例如 1 4(相当于2 4)

这个最后来的人来到了2号位子,前边留下了一个位子,

这个时候倒第二个人来的位子只能有两个,要么是0,要么是1(0表示在最后来的这个人前边,最后这个人没有插队,1表示最后这个人插队了)

1.倒第二个人来的位子是0 ,他直接站到了最后这个人前边留下的这个空位上。

2.倒第二个人来的位子1,(被插队了)这个时候这个人就只能站在最后这个人的后边了(被挤走了)

依次类推,我们能从最后一个人的位子来确定前边留下的空位.

这时候细心的小伙伴会问:那为什么我们不正向研究呢?

还是实例说明:第一个来的人是0 4直接站好第二个来的人是1 4直接站好,第三个人来的是 1 3 缺不能直接站好,我们要挪动第二个人的位子,与其要挪动一个人的位子,我们为啥不用倒序的思想呢?

所以我们这里的输入是这样的:


int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        build(1,n,1);//建树
        for(int i=0;i<n;i++)
        {
            scanf("%d%d",&pos[i],&val[i]);
        }
        for(int i=n-1;i>=0;i--)//倒序解问题。
        {
            query(pos[i]+1,val[i],1,n,1);
        }
        for(int i=1;i<=n;i++)
        {
            printf("%d ",ans[i]);
        }
        printf("\n");
    }
}

然后建个树:

#include<stdio.h>
#include<string.h>
using namespace std;
#define lson l,m,rt*2
#define rson m+1,r,rt*2+1
int tree[200005*4];
int pos[200005];
int val[200005];
int ans[200005];
void pushup(int rt)
{
    tree[rt]=tree[rt<<1]+tree[rt<<1|1];
}
void build( int l ,int r , int rt )
{
	if( l == r )
	{
		tree[rt]=1;//1表示这个位子是空位,0的话表示这个位子有人站好了.(而且思路保证这个人一旦站好了就不会再走了)
		return ;
	}
    int m = (l+r)>>1 ;
    build(lson) ;
    build(rson) ;
    pushup(rt) ;
}

然后是最主要的操作query,其实这里query操作也包括了update。我把操作放在了一起。操作也方便:

然后这里的难点就是空位多少的解决了。用题干给出的例子来看:

4
0 77
1 51
1 33
2 69
(倒序倒序倒序(重要的事情说三遍))

我们先来的人是 2 69 他要保证他的前边有几个空位呢?两个哦。他直接找第三个位子.去站好。

我们这里tree区间和表示的是区间空位的多少。然而找POS的方式如下:

    if(p<=tree[rt*2])query(p,v,lson);//如果左区间有足够的空位让他去保留,就去左边.
    else query(p-tree[rt*2],v,rson);//否则就去右边.

然后是完整的query操作:

void query(int p,int v,int l,int r,int rt)
{
    if(l==r)
    {
        tree[rt]-=1;//update操作
        ans[r]=v;//ans[l]=r
        return ;
    }
    int m=(l+r)/2;
    if(p<=tree[rt*2])query(p,v,lson);
    else query(p-tree[rt*2],v,rson);
    pushup(rt);
}
最后就是完整的AC代码:

#include<stdio.h>
#include<string.h>
using namespace std;
#define lson l,m,rt*2
#define rson m+1,r,rt*2+1
int tree[200005*4];
int pos[200005];
int val[200005];
int ans[200005];
void pushup(int rt)
{
    tree[rt]=tree[rt<<1]+tree[rt<<1|1];
}
void build( int l ,int r , int rt )
{
	if( l == r )
	{
		tree[rt]=1;
		return ;
	}
    int m = (l+r)>>1 ;
    build(lson) ;
    build(rson) ;
    pushup(rt) ;
}
void query(int p,int v,int l,int r,int rt)
{
    if(l==r)
    {
        tree[rt]-=1;
        ans[r]=v;
        return ;
    }
    int m=(l+r)/2;
    if(p<=tree[rt*2])query(p,v,lson);
    else query(p-tree[rt*2],v,rson);
    pushup(rt);
}
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        build(1,n,1);
        for(int i=0;i<n;i++)
        {
            scanf("%d%d",&pos[i],&val[i]);
        }
        for(int i=n-1;i>=0;i--)
        {
            query(pos[i]+1,val[i],1,n,1);
        }
        for(int i=1;i<=n;i++)
        {
            printf("%d ",ans[i]);
        }
        printf("\n");
    }
}









  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值