很久没有自己独立做出过题来了,我高兴!=-=
、题意比较简单,就是根据条件给定的位置给每个人进行排序,求最后的序列状态。(人就用一个唯一的数字表示)
说白了就是用线段树,每个节点保存在这个被维护的区间内有多少个空位置。
注意要倒过来处理每组数据,因为后面的数据位置不会随着前面的数据改变了。
这样就可以利用线段树的搞高效性进行处理数据,利用相对位置求出这个人在队列里面的最终位置。就是这样,不知说清楚了没=-=
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
const int maxn= 200100;
int pos[maxn];// 位置
int val[maxn];人
int nums[maxn];结果状态
struct node{int sum;int l;int r;int all;}str[maxn<<2];
void build(int l,int r,int rt){
str[rt].l=l;
str[rt].r=r;
str[rt].sum=0;
str[rt].all=str[rt].r-str[rt].l+1;
if(str[rt].l==str[rt].r){
return ;
}
int mid =(l+r)>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
return;
}
int query(int pos, int rt){//利用相对位置求绝对(最终)位置
if(str[rt].l==str[rt].r){
return str[rt].l;
}
if(str[rt<<1].all-str[rt<<1].sum>=pos){
return query(pos,rt<<1);
}
else{
return query(pos-str[rt<<1].all+str[rt<<1].sum,rt<<1|1);
}
}
void update(int idx,int num,int rt){//模拟插入每个人,更新nums[]
str[rt].sum++;
if(str[rt].l==str[rt].r){
nums[idx]=num;
// str[rt].sum=1;
return ;
}
int mid=(str[rt].l+str[rt].r)>>1;
if(mid>=idx)
update(idx,num,rt<<1);
else
update(idx,num,rt<<1|1);
return ;
}
int main()
{
//freopen("in.txt","r",stdin);
int n;
while(~scanf("%d",&n)){
for(int i=0;i<=n;i++)
nums[i]=-1;
for( int i=1; i<=n; i++ ){
int k;
scanf("%d%d",&k,&val[i]);
pos[i]=k+1;//转化为从1开始
}
build(1,n,1);
for(int i=n;i>=1;i--){
int idx=query(pos[i],1);
//printf("%d\n",idx);
//for(int j=1;j<=n;j++){
//printf("%d ",nums[j]);
//}
//puts("");
//while(nums[idx]>=0){
//idx++;
//}
update(idx,val[i],1);
}
for(int i=1;i<=n;i++)
printf("%d ",nums[i]);
puts("");
}
return 0;
}