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 #include <set>
 9 #include <stack>
10 #include <queue>
11 #include <string>
12 #include <iostream>
13 #include <algorithm>
14 using namespace std;
15
16 #define getmid(l,r) ((l) + ((r) - (l)) / 2)
17
18 typedef long long LL;
19 const double eps = 1e-8;
20 const int INF = (1 << 30) - 1;
21 const int maxn = 200005;
22
23 struct node{
24     int l,r,s;
25 }t[4*maxn];
26
27 struct Edge{
28     int pos,val;
29 }a[maxn];
30
31 int n;
32 int ans[maxn];
33
34 void Push_up(int p){
35     t[p].s = t[p<<1].s + t[p<<1|1].s;
36 }
37
38
39 void Build_tree(int p,int l,int r){
40     t[p].l = l;
41     t[p].r = r;
42     if(l == r){
43         t[p].s = 1;
44         return;
45     }
46     int mid = getmid(l,r);
47     Build_tree(p<<1,l,mid);
48     Build_tree(p<<1|1,mid+1,r);
49     Push_up(p);
50 }
51
52 void update(int idx,int p){
53     if(t[p].l == t[p].r){
54         t[p].s--;
55         return;
56     }
57     int mid = getmid(t[p].l,t[p].r);
58     if(idx <= mid) update(idx,p<<1);
59     else update(idx,p<<1|1);
60     Push_up(p);
61 }
62
63 int query(int idx,int p){
64     if(t[p].l == t[p].r) return t[p].l;
65     if(t[p<<1].s >= idx) return query(idx,p<<1);
66     else return query(idx-t[p<<1].s,p<<1|1);
67 }
68
69 void solve(){
70     Build_tree(1,1,n);
71 //    for(int i = 1;i <= 2*n;i++)
72 //    printf("t[%d].l = %d  t[%d].r = %d  t[%d].s = %d\n",i,t[i].l,i,t[i].r,i,t[i].s);
73     for(int i = n;i >= 1;i--){
74         int pos = a[i].pos;
75         int id = query(pos,1);
76         ans[id] = a[i].val;
77         update(id,1);
78     }
79     printf("%d",ans[1]);
80     for(int i = 2;i <= n;i++) printf(" %d",ans[i]);
81     printf("\n");
82 }
83
84 int main(){
85     while(scanf("%d",&n) != EOF){
86         for(int i = 1;i <= n;i++){
87             scanf("%d %d",&a[i].pos,&a[i].val);
88             a[i].pos++;
89         }
90         solve();
91     }
92     return 0;
93 }

加油啊~~~~

时间: 2024-12-26 17:19:17

poj 2828 Buy Tickets【线段树 单点更新】的相关文章

POJ 2828 Buy Tickets(线段树单点)

https://vjudge.net/problem/POJ-2828 题目意思:有n个数,进行n次操作,每次操作有两个数pos, ans.pos的意思是把ans放到第pos 位置的后面,pos后面的数就往后推一位.最后输出每个位置的ans. 思路:根据题 目可知,最后插入的位置的数才是最终不变的数,所以可以从最后的输入作第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

POJ 2828 Buy Tickets 线段树解法

此题应用线段树的方法非常巧妙.没做过真的难想得出是这么想的. 是一个逆向思维的运用. 其实一看到这道题目我就想到要运用逆向思维的了,但是就是没那么容易想通的. 思路: 1 要从后面往前更新线段树 2 线段树记录的是当前区间还剩下多少个记录空间 3 因为后面的插入会使得前面的插入往后退,那么前面插入的下标如果大于前面可以插入的空间,就需要往后退了. 好难理解的操作.仔细观察一下下面update这个函数吧. 二分地去查找适合的插入位置,把插入操作时间效率提高到 O(lgn),如果使用一般方法插入操作

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

Buy Tickets Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 12930   Accepted: 6412 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 (线段树)

题目大意: 排队有人插队,每一次都插到第 i 个人的后面. 最后输出顺序. 思路分析: 你会发现,如果反向处理的话,你就知道这个人是第几个了. 那么问题一下子就简化了. 就是在线段树上找第几个空位置就行了. #include <cstdio> #include <iostream> #include <cstring> #include <algorithm> #include <vector> #define lson num<<1

POJ 2828 Buy Tickets (线段树 or 树状数组+二分)

题目链接:http://poj.org/problem?id=2828 题意就是给你n个人,然后每个人按顺序插队,问你最终的顺序是怎么样的. 反过来做就很容易了,从最后一个人开始推,最后一个人位置很容易就确定了,那最后第二个人的位置也可以推(与最后一个人的位置无关)...依次就都可以确定所有的人了. 用前缀和的思想,要是这个人的位置确定了,那么就标记这个人位置的值为0,然后回溯更新,跟求逆序对个数的思想比较类似. 线段树: 1 #include <iostream> 2 #include &l

POJ 2828 Buy Tickets(线段树&#183;插队)

题意  n个人排队  每个人都有个属性值  依次输入n个pos[i]  val[i]  表示第i个人直接插到当前第pos[i]个人后面  他的属性值为val[i]  要求最后依次输出队中各个人的属性值 从头到尾看的话  队列是动态的   无法操作  但是反过来看时  pos[i]就可以表示第i个人前面还有多少个人了  然后想到了用线段树做就简单了  线段树维护对应区间还有多少个空位  每次把i放到前面刚好有pos[i]个空位的位置就行了  具体看代码 #include <cstdio> #de

POJ 2828 Buy Tickets | 线段树的喵用

题意: 给你n次插队操作,每次两个数,pos,w,意为在pos后插入一个权值为w的数; 最后输出1~n的权值 题解: 首先可以发现,最后一次插入的位置是准确的位置 所以这个就变成了若干个子问题, 所以用线段树维护一下每个区间剩余多少位置可选 对于一个pos 如果左儿子的剩余超过当前位置,就递归进左子树 反之就相当于留出了左儿子剩余的位置,递归进右子树,当前位置变成pos-左儿子剩余位置 请注意是在后面插入 1 #include<cstdio> 2 #include<algorithm&g

POJ 2828 poj 2828 Buy Tickets 【树状数组,已知前n项和为K,返回n值】

题目链接:http://poj.org/problem?id=2828 在一个队列中,一个人想要插队,告诉你每个新来的人会插在i个人后面,求出最后的队列. 如果我们用模拟的话,那么时间复杂度肯定是超了:想想,如果我们逆序,那么最后来的人的位置一定是固定的,这样的话,我们将问题转化成逆序扫描给出数据,插在i个人后面这个数据就变成了在这个人前面需要留出多少个空位.如此我们只需要用树状数组记录前n项总共有多少个空位,每扫描一个数据,就找出能使得他前面正好有i个空位. 这题用树状数组或者线段树都可以,今

POJ 3264 Balanced Lineup (线段树单点更新 区间查询)

Balanced Lineup Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 36820   Accepted: 17244 Case Time Limit: 2000MS Description For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000) always line up in the same order. One day Farmer Joh