您的位置:首页 > 其它

poj 2828

2015-08-01 10:31 405 查看
Buy TicketsDescriptionRailway 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 jumpedthe 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.InputThere 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 inthe increasing order of i (1 ≤ i ≤ N). For each i, the ranges and meanings of Posi and Valiare 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 queuewas 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.OutputFor 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
题目大意:插队问题。已知有N个人,一开始队列为空,编号从1到N,可以看作所有人
都排在0号的后面(0号不存在)。分别读入N个人的pos 和 val,pos 表示插
队在 pos号人的后面(如pos = 0, 即插入到第1位),val 可以看作是读入的
人的一个标识。求经过N次插队以后(插队一定成功),最终的队列(输出这
个队列每个人的标识值)。
思      路: 刚开始知道用线段树没有思路,看了别人的总结慢慢的学会往正确的方向上想了。
这道题就是倒着从最后一个开始找,找到那个之前有data[i]个空位的序号、详情见代码解释。
线段树相当于统计一些离散化的数或者点,建树的过程中已经把他们的序号存储下了,
把他们都个体化之后对于共同的特点进行统计。
见过几道题情况大致为:
1 : 在某些范围内修改或者变动数据。此时序号和数据无关,sum数组存储数据的和
同时需要不断的更新sum数组。
2 :查找一系列数的逆序数。查找已经出现的比每个数大的数的个数,sum存储的是
结点的个数之和,在题目要求的情况下序号正好是数据,因此通过查找sum值并且
更新就可以找到答案。
3 : 第三类就是这种情况了,将每个数据看成个体,查找第n个数的后一位的序号。
                        sum存储的是未被使用的结点的个数
值得注意的是,在query返回值得时候,要考虑是当前这个还是下一个。
if (i < n )   返回的是符合i<n的下一个
if (i< = n)  返回的是符合i<=n的当前这个
还要注意sum数组代表的含义。要理清序号,sum数组值,当前查找的i (j)之间的关系
代码如下:
<pre name="code" class="cpp">/*踏实!!努力!!*/#include<iostream>#include<stdio.h>#include<cmath>#include<cstring>#include<map>#include<queue>#include<stack>using namespace std;#define N 200010int n;int sum[N<<2];struct{int pos;int val;}data;void build(int l,int r,int cur){if(l==r){sum[cur]=1;//初始的时候每个位置都标记一下return ;}int mid=(l+r)>>1;build(l,mid,cur<<1);build(mid+1,r,cur<<1|1);sum[cur]=sum[cur<<1]+sum[cur<<1|1];return ;}int query(int i,int l,int r,int cur){if(l==r){sum[cur]=0;return l;}int ans=0;int mid=(l+r)>>1;//注意这里不是i<=sum[cur<<1]查找的是前面有i个空位的位置if(i<sum[cur<<1])ans=query(i,l,mid,cur<<1);//注意这里是i-sum[cur<<1]  查找的数量发生变化elseans=query(i-sum[cur<<1],mid+1,r,cur<<1|1);sum[cur]=sum[cur<<1]+sum[cur<<1|1];return ans;}int main(){int ans;while(scanf("%d",&n)!=EOF){build(1,n,1);for(int i=1;i<=n;i++)scanf("%d%d",&data[i].pos,&data[i].val);for(int i=n;i>=1;i--){int index=query(data[i].pos,1,n,1);ans[index]=data[i].val;//存储对应位置的val值}printf("%d",ans[1]);for(int i=2;i<=n;i++)printf(" %d",ans[i]);printf("\n");}return 0;}

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: