线段数应用(poj2828)

本文针对BuyTickets问题提出了解决方案,利用线段树数据结构进行高效处理。详细介绍了算法思路及实现过程,包括节点定义、初始化、插入操作等关键步骤。

线段数应用

题目Buy Tickets

题目大意:n个人排队等待,第i个人到来会有两个信息(Pos[i]∈ [0, i − 1] , val[i])表明这

个人会插队到pos[i]的后边,这个人的值是val[i];  依次给出n个人的到来信息,输出最终的

队列从头到尾每个人的值。

思路:第i个人插入的位置是pos[i]那就说明这个人前面要有pos[i]个空位置重后向前依次插入到线段数中,假设第i个人插入到了位置x,那么[0,x - 1]必须有(pos[i])个空位置留给在i之前到来且排在i前的人(这样的人必然有,要不然第i个人的插入操作就是错误的)。

提交情况 : WA 2次  AC 1次

               原因:没搞清思路;

 

ACcode

/*
	题目:http://poj.org/problem?id=2828  Buy Tickets
	n个人排队等待,第i个人到来会有两个信息(Pos[i] ∈ [0, i − 1] , val[i])表明这个人会插队到pos[i]的后边,这个人的值是val[i];
	依次给出n个人的到来信息,输出最终的队列。
*/

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

#define maxn 200100
int num[maxn];

/* 线段数节点(有了类以后,程序的组织确实边的舒服了,这里的mid就是个好例子) */
struct segmentTreeNode{  
    int l, r, sit;
    segmentTreeNode* son[2];
	int mid(){ return (l + r) >> 1; }
    void init(int _l, int _r, int _sit, segmentTreeNode* sonl, segmentTreeNode* sonr){
        l = _l, r = _r, sit = _sit, son[0] = sonl, son[1] = sonr;
    }
};

struct humNode{
    int sate, id;
}hum[maxn];

/* 线段数结构 */
struct segmentTree{
    segmentTreeNode* root, * link;
    int ad;
    segmentTree(){
        root = NULL;
        link = new segmentTreeNode[maxn * 4];
        ad = 0;
    }
    ~segmentTree(){ delete[] link; }
    void built(int l, int r, segmentTreeNode* &rt){
        if(l > r) return;
        rt = &link[ad ++];
        rt->init(l, r, r - l + 1, NULL, NULL);
		if(l == r) return;
		built(l, rt->mid(), rt->son[0]);
		built(rt->mid() + 1, r, rt->son[1]);
    }
	void insert(int sate, int id, segmentTreeNode* rt){
		rt->sit --;
		if(rt->l == rt->r){
            num[rt->l] = id;
            return;
		}
		if(rt->son[0]->sit >= sate) insert(sate, id, rt->son[0]);
		else insert(sate - rt->son[0]->sit, id, rt->son[1]);
    }
};

int main(){
    int n;
    while(~scanf("%d", &n)){
        segmentTree seg;
        seg.built(0, n - 1, seg.root);
        for(int i = 0; i < n; ++ i) scanf("%d %d", &hum[i].sate, &hum[i].id);
        for(int i = n - 1; i >= 0; -- i){
			seg.insert(hum[i].sate + 1, hum[i].id, seg.root);
        }
        for(int i = 0; i < n - 1; ++ i) printf("%d ", num[i]);
        printf("%d\n", num[n - 1]);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值