poj 2828 Buy Tickets

题目的意思是给出一些人插队的顺序,求出最后插完的队列结果

可以用反向推到的方法,最后一个插入的点,前面有pos[n-1]个座位,以此类推

可以想到用线段树的方法记录一个线段的座位的个数,不断地更新线段树

顺便介绍一个线段树的文章:http://www.notonlysuccess.com/index.php/segment-tree-complete/

#include<iostream>

#include<cstring>
#include<cstdio>
using namespace std;
#define M 410000
struct Tree{
int c;//结点还有多少个空位
int left,right;


}tree[M*2];
int pos[M],val[M];
int ans[M];
void init(int p,int left,int right){
tree[p].c = right-left+1;
tree[p].left = left;
tree[p].right = right;
if(left==right)return ;
int mid = left+(right-left)/2;
init(p*2,left,mid);
init(p*2+1,mid+1,right);
}
int id;
void update(int p,int Pos){
tree[p].c--;
if(tree[p].left==tree[p].right){
id = tree[p].left;
return ;
}
int mid = (tree[p].left+tree[p].right)/2;
if(tree[p*2].c<Pos){
Pos-=tree[p*2].c;
update(p*2+1,Pos);
}else update(p*2,Pos);
}
int main(){
int n;
while(scanf("%d",&n)!=EOF){
init(1,1,n);
for(int i = 0;i<n;i++)scanf("%d%d",&pos[i],&val[i]);
for(int i = n-1;i>=0;i--){
update(1,pos[i]+1);
ans[id] = val[i];
}
for(int i = 1;i<=n;i++)printf("%d%c",ans[i],i==n?'\n':' ');
}
}

猜你喜欢

转载自blog.csdn.net/sysucph/article/details/9027041