Buy Tickets+POJ+线段树单点更新的灵活运用

Buy Tickets

Time Limit: 4000MS   Memory Limit: 65536K
Total Submissions: 12927   Accepted: 6410

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
解决方案:虽知暴力会t,但还是直接线段树暴力,果然无情地t了。看了别人的题解才知,可以从后往前插,因为后面的位置往往是确定的,不用挪。可以这样想,有n个人,最后一个人n要呆在s[n]位子,那么它的位置就固定是s[n],少了最后一个人,又变成了从对n-1个人插队,又从剩下的位置开始数,遇到被占得跳过,数到s[n-1],那么它的位置也就确定了,如此类推,既可以把所有人的排队情况搞出来。
code:
#include<iostream>
#include<cstdio>
#include<cstring>
#define MMAX 2000002
using namespace std;
int sum[4*MMAX];
int ans[MMAX];
int index;
int n;
struct node
{
    int v,s;
} Num[MMAX];
void build(int rt,int L,int R)
{

    if(L==R)
    {
        sum[rt]=1;
    }
    else
    {
        int M=(L+R)/2;
        build(rt*2,L,M);
        build(rt*2+1,M+1,R);
        sum[rt]=sum[rt*2]+sum[rt*2+1];
    }

}
void update(int rt,int L,int R,int S)
{
    sum[rt]--;
    if(L==R)
    {
        index=L;
    }
    else
    {
        int M=(L+R)/2;
        if(S<=sum[rt*2]) update(rt*2,L,M,S);
        else
        {
            S-=sum[rt*2];
            update(rt*2+1,M+1,R,S);
        }

    }

}
int main()
{
    while(~scanf("%d",&n))
    {
        build(1,1,n);
        for(int i=0; i<n; i++)
        {
            scanf("%d%d",&Num[i].s,&Num[i].v);
        }
        for(int i=n-1; i>=0; i--)
        {
            update(1,1,n,Num[i].s+1) ;
            ans[index]=Num[i].v;
        }
        for(int i=1; i<=n; i++)
        {
            printf("%d%c",ans[i],i==n?'\n':' ');
        }
    }
    return 0;
}

Buy Tickets+POJ+线段树单点更新的灵活运用

时间: 2024-10-28 21:06:08

Buy Tickets+POJ+线段树单点更新的灵活运用的相关文章

POJ 2828 Buy Tickets (线段树 单点更新 变形)

题目链接 题意:有N个人排队,给出各个人想插队的位置和标识,要求输出最后的序列. 分析:因为之前的序列会因为插队而变化,如果直接算时间复杂度很高,所以可以用 线段树逆序插入,把序列都插到最后一层,len记录该区间里还剩余多少位置,插入的时候就插到剩余的第几个位置, 比如1,2已经插入了,如果再想插入第3个位置,则实际上插入的是5. 因为是逆序的,所以在3之前除了现在的1,2 还有之前的1,2. 1 #include <iostream> 2 #include <cstdio> 3

poj 2828 Buy Tickets【线段树单点更新】【逆序输入】

Buy Tickets Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 16273   Accepted: 8098 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 wa

POJ 2828 Buy Tickets (线段树 单点更新 插队问题)

题目链接:http://poj.org/problem?id=2828 题意:有个家伙春节买票,闲的没事想了一个让我们做= =!,是酱紫的,有n个人,编号是val,将插队,其序号变为pos,编号的范围[0,n). 刚开始真心没有看出来是个线段树题,要不是在做线段树专题,打死我也不会向线段树上靠拢. 想想这是用线段树解决一个什么样的模型呢? 1:每个人有固定的位置,虽然中途在不停加入,但到最后,一个萝卜一个坑 2:是不停加入成员,而不是改变 3:用线段树记录空余位置 没想到用线段树是我遇到的第一个

POJ 2828 Buy Tickets(线段树--单点更新)

Buy Tickets Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 16196   Accepted: 8059 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 wa

Buy Tickets(线段树单点更新,逆向思维)

题目大意:有n个的排队,每一个人都有一个val来对应,每一个后来人都会插入当前队伍的某一个位置pos.要求把队伍最后的状态输出. 个人心得:哈哈,用链表写了下,果不其然超时了,后面转念一想要用静态数组思维, 还是炸了.大牛们很给力,逆向一转,真是服气. 一想是呀,转过来的话那么此时的人必然可以得到他的位置,此时更新长度,后面的人在此时的队列中依旧可以得到他想要的位置. 就算思路知道了,怎么实现呢,大神果然不愧是大神,线段树sum表示总长度,节点表示是否存在被占据,然后更新就可以了. 真的是佩服到

poj2828 buy tickets(线段树单点更新)

题目链接: huangjing 思路: 因为给出了n条插入,所以如果正推的话,那么后面插的会影响到最后所在的位置,所以考虑逆序解决,那么如果此人站在第i个人的位置,那么这个人前面必然有i个空位置没占,因为是从后向前考虑的,所以每次更新的时候就要考虑在前面存在i个空位的位置后插入这个人,那么最后得到的序列就是满足条件的.. 题目: Language: Default Buy Tickets Time Limit: 4000MS   Memory Limit: 65536K Total Submis

poj 2828 Buy Tickets【线段树 单点更新】

倒着插,先不理解意思,后来看一篇题解说模拟一下 手动模拟一下就好理解了----- 不过话说一直写挫---一直改啊----- 好心塞------ 1 #include <cstdio> 2 #include <ctime> 3 #include <cstring> 4 #include <cstdlib> 5 #include <cmath> 6 #include <vector> 7 #include <map> 8 #i

poj 2828 Buy Tickets 【线段树点更新】

题目:poj 2828 Buy Tickets 题意:有n个人排队,每个人有一个价值和要插的位置,然后当要插的位置上有人时所有的人向后移动一位当这个插入到这儿,如果没有直接插进去. 分析:分析发现直接插入移动的话花时间太多,我们可不可以用逆向思维.从后往前来,因为最后一个位置是肯定能确定的,而其他的则插入空的第某个位置. 比如第一组样例: 4 0 77 1 51 1 33 2 69 开始时候位置都为空 编号0 1 2 3 首先从最后一个来2 69 第二个位置空,则可以直接放 然后编号变为0 1

POJ训练计划2828_Buy Tickets(线段树/单点更新)

解题报告 题意: 插队完的顺序. 思路: 倒着处理数据,第i个人占据第j=pos[i]+1个的空位. 线段树维护区间空位信息. #include <iostream> #include <cstdio> #include <cstring> using namespace std; struct node { int x,v; } num[201000]; int sum[1000000],ans[201000]; void cbtree(int rt,int l,in