POJ 2828Buy Tickets

POJ 2828

题目大意是说有n个插入操作,每次把B插入到位置A,原来A以后的全部往后移动1,球最后的序列

tree里保存的应该是这整个区间还有多扫个位置可以插入数据,那么线段树里从后往前扫描依次插入数据

比如现在吧B插入到A位置,如果整个区间左侧还有<A个位置可以插入数据,那么就只能将其放到整个区间的右侧,递归下去就可以了

 1 void update(int k, int L, int R, int x)
 2 {
 3     if(L == R) { pre[k] = r; ans[L] = val; return ; }
 4
 5     int mid = (L+R)>>1;
 6
 7     if(x <= pre[k<<1]) update(lson, x);//左侧的多余x
 8
 9     else update(rson, x-pre[k<<1]);//否则往右
10
11      pre[k] = pre[k<<1] + pre[k<<1|1];
12 }
 1 #include <map>
 2 #include <set>
 3 #include <stack>
 4 #include <queue>
 5 #include <cmath>
 6 #include <ctime>
 7 #include <vector>
 8 #include <cstdio>
 9 #include <cctype>
10 #include <cstring>
11 #include <cstdlib>
12 #include <iostream>
13 #include <algorithm>
14 using namespace std;
15 #define INF 1e9
16 #define inf (-((LL)1<<40))
17 #define lson k<<1, L, mid
18 #define rson k<<1|1, mid+1, R
19 #define mem0(a) memset(a,0,sizeof(a))
20 #define mem1(a) memset(a,-1,sizeof(a))
21 #define mem(a, b) memset(a, b, sizeof(a))
22 #define FOPENIN(IN) freopen(IN, "r", stdin)
23 #define FOPENOUT(OUT) freopen(OUT, "w", stdout)
24 template<class T> T CMP_MIN(T a, T b) { return a < b; }
25 template<class T> T CMP_MAX(T a, T b) { return a > b; }
26 template<class T> T MAX(T a, T b) { return a > b ? a : b; }
27 template<class T> T MIN(T a, T b) { return a < b ? a : b; }
28 template<class T> T GCD(T a, T b) { return b ? GCD(b, a%b) : a; }
29 template<class T> T LCM(T a, T b) { return a / GCD(a,b) * b;    }
30
31 typedef __int64 LL;
32 //typedef long long LL;
33 const int MAXN = 200005;
34 const int MAXM = 100005;
35 const double eps = 1e-10;
36 const LL MOD = 1000000007;
37
38 int N, pre[MAXN<<2];
39 int id[MAXN], num[MAXN], ans[MAXN];
40 int r, val;
41
42 int buildTree(int k, int L, int R)
43 {
44     if(L == R) return pre[k] = 1;
45     int mid = (L+R)>>1;
46     return pre[k] = buildTree(lson) + buildTree(rson);
47 }
48
49 void update(int k, int L, int R, int x)
50 {
51     if(L == R) { pre[k] = r; ans[L] = val; return ; }
52
53     int mid = (L+R)>>1;
54
55     if(x <= pre[k<<1]) update(lson, x);
56
57     else update(rson, x-pre[k<<1]);
58
59      pre[k] = pre[k<<1] + pre[k<<1|1];
60 }
61
62 int main()
63 {
64     while(~scanf("%d", &N))
65     {
66         buildTree(1, 1, N);
67         for(int l=1;l<=N;l++)
68             scanf("%d %d", &id[l], &num[l]);
69         r = 0;
70         for(int i=N;i>0;i--)
71         {
72             val = num[i];
73             update(1, 1, N, id[i] + 1);
74         }
75         for(int i=1;i<=N;i++) printf("%d%c", ans[i], i==N?‘\n‘:‘ ‘);
76     }
77     return 0;
78 }

POJ 2828Buy Tickets

时间: 2024-11-13 06:43:01

POJ 2828Buy Tickets的相关文章

POJ 2828Buy Tickets(线段树的单点维护)

Buy Tickets Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 20462   Accepted: 10096 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 w

poj Buy Tickets

题目链接:http://poj.org/problem?id=2828 类似的题目:http://www.cnblogs.com/lovychen/p/3674048.html 测试数据: in: 40 771 511 332 6940 205231 192431 38900 31492 out: 77 33 69 5131492 20523 3890 19243 题目分析:直接倒着进行插入,然后按照从前向后寻找空位进行插入: [题解]: 线段树节点中保存这一段中的空位数,然后倒序对pos插入:

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(线段树)

Language: Default Buy Tickets Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 13847   Accepted: 6926 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

poj 2828 Buy Tickets

Buy Tickets Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 13277   Accepted: 6595 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个人占据第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 (线段树)

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

POJ 2828 Buy Tickets 线段树解法

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

【POJ】2828 Buy Tickets(线段树+特殊的技巧/splay)

http://poj.org/problem?id=2828 一开始敲了个splay,直接模拟. tle了.. 常数太大.. 好吧,说是用线段树.. 而且思想很拽.. (貌似很久以前写过貌似的,,) 我们线段树维护的区间不再是人了.. 而是这个区间剩余的的座位.. 比如我现在要坐第一张,但是人已经坐了,即这个区间已经没有位置了..那就要往后坐. 所以我们逆序添加,,因为后来人插队前边人管不着... 所以后来人一定是先定座位的.. 每一次维护这个座位区间.. 如果左边这个区间座位比我要坐的座位号要