线段数应用
题目: 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;
}