POJ 2828 线段树应用

这道题是之前一场比赛碰到的题目,当时看到题时以为是一道用链表优化的水题,交了几遍一直超时,简直不能再感人(┬_┬)今天有空突然想起去查了下题解,是用线段树做的。。。。。完全想不到啊有木有~思路大概就是每个节点存当前节点下还剩多少空位,然后倒序查找该人所需要的位置,具体细节看代码吧。

Buy Tickets

Time Limit: 4000MS   Memory Limit: 65536K
Total Submissions: 15801   Accepted: 7876

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

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<queue>
 6 #include<stack>
 7 #include<string>
 8 using namespace std;
 9 #define N 100005
10 #define inf 0x7fffffff
11 int node[N*8],num[N*2];
12 struct ss
13 {
14     int p,v;
15 } pos[N*2];
16 void buildtree(int root,int l,int r)
17 {
18     node[root]=r-l+1;
19     if(l==r) return ;
20     buildtree(root*2,l,(l+r)/2);
21     buildtree(root*2+1,(l+r)/2+1,r);
22 }
23 int query(int p,int l,int r,int root)
24 {
25     node[root]--;
26     if(l==r)return l;
27     int m=(l+r)/2;
28     if(node[root*2]>=p)
29         return query(p,l,m,root*2);
30     else
31         return query(p-node[root*2],m+1,r,root*2+1);
32 }
33 int main()
34 {
35     int n,i,j;
36     while(~scanf("%d",&n))
37     {
38         for(i=0;i<n;i++)
39             scanf("%d%d",&pos[i].p,&pos[i].v);
40         buildtree(1,1,n);
41         for(i=n-1;i>=0;i--)
42             num[query(pos[i].p+1,1,n,1)]=pos[i].v;
43         for(i=1;i<n;i++)
44             printf("%d ",num[i]);
45         printf("%d\n",num[n]);
46     }
47     return 0;
48 }

时间: 2024-10-08 15:35:57

POJ 2828 线段树应用的相关文章

poj 2828 线段树

http://poj.org/problem?id=2828 学到的思维: 1.变化的或者后来的优先影响前面的,那么从最后一个往前看,最后一个就成了 确定的, 并且后来的也可以确定----如果从前往后,所有的随时都不是确定的 2.线段树叶子节点直接维护区间(线段)信息,非叶子节点v维护的是以v为树根的整个子树的信息,那么假设父节点rt信息为[l,r]那么左子树维护[l,mid],右子树维护[mid+1,r]的信息.如果如果是前缀和,rt里是1-n的和,左子树1~n/2的和,右子树是n/2+1~n

poj 2828(线段树 逆向思考) 插队是不好的行为

http://poj.org/problem?id=2828 插队问题,n个人,下面n行每行a,b表示这个人插在第a个人的后面和这个人的编号为b,最后输出队伍的情况 涉及到节点的问题可以用到线段树,这里因为每个人插队时有顺序的,如果按照正着的顺序来情况太复杂,所以可以试试倒过来,从最后一个人开始,此时找到的位置 一定是最终位置,这样就很简单了,   结构体中多开一个mark表示每个区间的空位置,多开一个sum表示人的编号 这道题不错,提醒我们有时候换一换思路,逆向思考一下 1 #include<

poj 2828(线段树单点更新)

Buy Tickets Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 18561   Accepted: 9209 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 Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 15422   Accepted: 7684 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 线段树插孔处理

给你一个数列出现的先后顺序num[i]和对应数值   输出最后排好序的对应数值,如 4 0 77 1 51 1 33 2 69 第一步  77 第二部 77  51 第三步 77  33 51 第四部77  33  69 51 后面先出现的位置是固定的  所以从后往前处理. 线段树每个节点存当前区间还有多少个空位: #include<stdio.h> #include<string.h> #include<iostream> using namespace std; #

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

倒着插,倒着插,这道题是倒着插! 想一下如果 Posi 里面有若干个0,那么排在最前面的一定是最后一个0. 从后往前看,对于第i个数,就应该插在第Posi + 1个空位上,所以用线段树来维护区间空位的个数. 说一下那个坑爹的第56行的判断: if(i > 1) printf(" "); 将输出的n个数用空格隔开,我感觉这是一个还算常用的写法啊,结果各种莫名TLE,加上输入挂也补救不回来. 去掉这个无谓的判断后,3594MS险过,加上输入挂3094MS,还算是起到了一定的加速作用.

Buy Tickets POJ - 2828线段树求插队

题意就是给你n个人,每个人有自己的要插入的pos和val,问你最后的排序 思路:逆序插入,最后一个人的位置一定是固定的,因为必须连续插入,所以第i个人插入的时候必须保证前面有pos[i]个空位, 那么用线段树记录位置个数,如果位置不够,就往后挪. #include<iostream> #include<cstdio> using namespace std; #define N 200005 int spare[N<<2]; int seq[N]; int pos[N]

POJ 2828 线段树单点更新 离线搞

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 ha

POJ 2528 (线段树+离散化) Mayor&#39;s posters

因为将每个单位都作为一个最小单元的话会爆内存的 所以,将海报的每个端点进行排序,将这些端点最为最小的区间. 毕竟是刚刚接触线段树,理解起来还有些吃力,还是那句话,题做多了慢慢就好了. 萌萌的AC代码君贴上. 1 //#define LOCAL 2 #include <iostream> 3 #include <algorithm> 4 #include <cmath> 5 using namespace std; 6 7 int n; 8 struct CPost 9