poj 2828 Buy Tickets(数据结构:线段树)

来源:互联网 发布:java drawimage 厘米 编辑:程序博客网 时间:2024/06/14 06:33

看了别人的思路才知道怎么写的...

不然根本看不出和线段树有什么关系

因为每次进队都是在第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 longusing 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;}



0 0
原创粉丝点击