poj 2828 Buy Tickets(数据结构:线段树)
2014-08-02 17:00
387 查看
看了别人的思路才知道怎么写的...
不然根本看不出和线段树有什么关系
因为每次进队都是在第pos[i]个人后面,所以我们逆序推的话可以知道第i个人前面有pos[i]个空位
那这样的话我们用线段树来记录l-r范围内空位置的数量
对于逆序的Pos数组进行单点更新即可,把val[i]放在前面有pos[i]个空位的位置
感觉开始理解线段树的思想了,做题的时候最好先把相应的线段树画出来
代码如下:
不然根本看不出和线段树有什么关系
因为每次进队都是在第pos[i]个人后面,所以我们逆序推的话可以知道第i个人前面有pos[i]个空位
那这样的话我们用线段树来记录l-r范围内空位置的数量
对于逆序的Pos数组进行单点更新即可,把val[i]放在前面有pos[i]个空位的位置
感觉开始理解线段树的思想了,做题的时候最好先把相应的线段树画出来
代码如下:
/* * 逆序遍历,每次把val[i]放置在前面还有pos[i]个空位置的位置 * 线段树节点中记录的是cnt表示l-r这段区间内空位置的数量 */ #include <cstdio> #include <iostream> #include <algorithm> #define MAXN 200010 #define LL long long using namespace std; int pos[MAXN], val[MAXN], cnt[MAXN<<2], ans[MAXN]; void pushUp(int rt) { cnt[rt] = cnt[rt<<1] + cnt[rt<<1|1]; } void build(int l, int r, int rt) { cnt[rt] = r-l+1; if(l == r) return ; int m = (l+r) / 2; build(l, m, rt<<1); build(m+1, r, rt<<1|1); } void update(int p, int val, int l, int r, int rt) { cnt[rt]--; if(l == r) { ans[l-1] = val; return ; } int m = (l+r)/2; if(cnt[rt<<1] > p) update(p, val, l, m, rt<<1); else update(p-cnt[rt<<1], val, m+1, r, rt<<1|1); pushUp(rt); } int main(void) { int n; while(scanf("%d", &n) != EOF) { build(1, n, 1); for(int i=0; i<n; ++i) { scanf("%d%d", &pos[i], &val[i]); } for(int i=n-1; i>=0; --i) { update(pos[i], val[i], 1, n, 1); } printf("%d", ans[0]); for(int i=1; i<n; ++i) printf(" %d", ans[i]); cout << endl; } return 0; }
相关文章推荐
- POJ 2828 Buy Tickets [线段树-单点更新]【数据结构】【好题】
- poj 2828--Buy Tickets(线段树)
- poj 2828 Buy Tickets(动态队列·线段树单点更新)
- POJ 2828 Buy Tickets(多校连萌,线段树模拟插入)
- POJ 2828 Buy Tickets(线段树)
- POJ 2828 Buy Tickets (树状数组 or 线段树)
- POJ Buy Tickets 2828(线段树)
- POJ-2828 Buy Tickets 线段树
- POJ-2828 Buy Tickets 线段树
- POJ 2828 - Buy Tickets(线段树)
- Buy Tickets - POJ 2828 线段树
- poj 2828 Buy Tickets(树状数组 | 线段树)
- poj 2828 Buy Tickets (排队问题+线段树)
- POJ 2828 Buy Tickets 线段树 单点修改记录状态
- POJ 2828 Buy Tickets(线段树)
- poj 2828 Buy Tickets 线段树!!!
- POJ 2828 Buy Tickets (线段树,插队问题)
- poj 2828 Buy Tickets(线段树)
- poj 2828 Buy Tickets 线段树
- POJ 2828 Buy Tickets 线段树