poj 2828 Buy Tickets (线段树)

小记: 这题之前想的简单了, 后来看了样例,发现了自己想法的错误


思路:一开始便发现这题,应该反过来思考的。但是用线段树解决还是有点没想到。

方法是:从后面开始看起,这样计算完它之后,计算后面的值的时候不会影响之前计算过了的结果。相当于无后效性

对每个值 有一个 pos值,那么其所在位置至少是pos+1之后,因为pos值是从0开始的,正常的位置是从1开始的

所以,以pos值建线段树, 目的是在pos+1位置处放下当前的value,而有可能pos+1位置已经被占用了,所以要往后推

这里我们给线段树的每个节点加一个space,代表这一段还有多少个位置可以使用,因为pos+1是从1开始数起的,

所以线段树二分时,左边的空间够的话,就直接进入左边,什么都不用改,而若不够,则要进入右边,但是值要减去左边的space值,

这样求得最后的位置就必然是答案了,而当那个位置确定下来的时候,我们就应该记录下来,开个数组记录即可。


代码:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <map>
#include <set>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>

using namespace std;

#define mst(a,b) memset(a,b,sizeof(a))
#define REP(a,b,c) for(int a = b; a < c; ++a)
#define eps 10e-8

const int MAX_ = 200010;
const int N = 100010;
const int INF = 0x7fffffff;

struct node{
    int l, r;
    int space;
}tree[MAX_*5];

int ans[MAX_];
int a[MAX_], b[MAX_];

void build(int l, int r, int k)
{
    if(l == r){
        tree[k].l = l;
        tree[k].r = r;
        tree[k].space = 1;
        return ;
    }

    int mid = l + (r-l)/2;
    tree[k].l = l;
    tree[k].r = r;

    build(l, mid, k<<1);
    build(mid+1, r, (k<<1)|1);

    tree[k].space = tree[k<<1].space + tree[(k<<1)|1].space;

}

void insert(int p, int value, int k)
{
    if(tree[k].l == tree[k].r){
        tree[k].space = 0;
        ans[tree[k].l] = value;
        return ;
    }

    if(p <= tree[k<<1].space){
        insert(p, value, k<<1);
    }
    else{
        insert(p-tree[k<<1].space, value, (k<<1)|1);
    }

    tree[k].space = tree[k<<1].space + tree[(k<<1)|1].space;
}


int main(){
	int n, m;
	while(~scanf("%d", &n)){
        REP(i, 0, n){
            scanf("%d%d", &a[i], &b[i]);
        }
        build(0, n-1, 1);

        for(int i = n-1; i > -1; --i){
            insert(a[i]+1, b[i], 1);
        }

        printf("%d", ans[0]);
        REP(i, 1, n){
            printf(" %d",ans[i]);
        }
        printf("\n");
	}
	return 0;
}


你可能感兴趣的:(poj 2828 Buy Tickets (线段树))