POJ2828--Buy Tickets(线段树,单点更新)

题目大意:火车站正在排队,有人插队(竟插队成功?),给出插入的位置,和那个人权值,求最后形成的队列。

分析:一直没想出来怎么做,只知道肯定要用树来做,不然绝对超时。然后,搜到一份蛮容易看懂的题解

http://www.cnblogs.com/CheeseZH/archive/2012/04/29/2476134.html


代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int maxn = 200010;

struct Tree {
    int a, w;
};

struct Node {
    int p, w;
};

int n;
Tree t[3*maxn];
Node q[maxn];
void Build(int root, int l, int r) {
    t[root].a = r-l+1;
    t[root].w = -1;
    if(l != r) {
        Build(2*root+1, l, (l+r)/2);
        Build(2*root+2, (l+r)/2+1, r);
    }
}

void Insert(int root, int l, int r, int p, int w) {
    t[root].a--;
    if(l == r) {
        t[root].w = w;
    }
    else if(t[2*root+1].a < p) {
        Insert(2*root+2, (l+r)/2+1, r, p-t[2*root+1].a, w);
    }
    else {
        Insert(2*root+1, l, (l+r)/2, p, w);
    }
    return;
}

void Print(int root, int l, int r) {
    if(l == r) {
        printf("%d ", t[root].w);
        return;
    }
    Print(2*root+1, l, (l+r)/2);
    Print(2*root+2, (l+r)/2+1, r);
    return;
}

int main() {
    while(~scanf("%d", &n)) {
        Build(0, 1, n);
        for(int i = 0; i < n; i++) {
            int p, w;
            scanf("%d%d", &p, &w);
            q[i].p = p+1, q[i].w = w;
        }

        for(int i = n-1; i >= 0; i--)
            Insert(0, 1, n, q[i].p, q[i].w);
        Print(0, 1, n);
        printf("\n");
    }
    return 0;
}


你可能感兴趣的:(POJ2828--Buy Tickets(线段树,单点更新))