poj 2828 (线段树查询第k小+离线处理

题意:
排队问题,每次把vali插到posi的位置,问最后的序列

思路:
如果顺着做的话,复杂度n^2无法接受,我们可以发现一个重要的性质,前面的数对后面的没有影响,后面插入的对前面有影响,所以倒序处理,每个插入的位置其实是在当前所有排位的第posi+1个空位的位置 这个很容易证明,在原有的左边插入,不会影响,在右边插入,会根据之前插入过的个数倒退,所以就是第posi+1个空位,线段树或者树状数组搞搞就好了

#include<iostream>
#include<cstdio>
#include<cstring>
#define lson p<<1,l,mid
#define rson p<<1|1,mid+1,r
#define ls p<<1
#define rs p<<1|1
using namespace std;
const int maxn=2e5+5;
int sum[maxn<<2];
int pos[maxn],val[maxn],n,ans[maxn];
void pushUp(int p)
{
   sum[p]=sum[ls]+sum[rs]; 
}
void build(int p,int l,int r)
{
   if(l==r){ sum[p]=1;return;}
   int mid=l+r>>1;
   build(lson);
   build(rson);
   pushUp(p); 
}
void update(int p,int l,int r,int num,int x)
{
   if(l==r&&sum[p]==1)
   { 
      ans[l]=val[x],sum[p]=0;
      return;
   }
   int mid=l+r>>1;
   if(num>sum[ls])
      update(rson,num-sum[ls],x);
   else 
      update(lson,num,x);
   pushUp(p); 
}
int main()
{
    while(~scanf("%d",&n))
    { 
       for(int i=1;i<=n;++i)
           scanf("%d%d",&pos[i],&val[i]);
       build(1,0,n-1);
       for(int i=n;i;--i)
          update(1,0,n-1,pos[i]+1,i); 
       for(int i=0;i<=n-1;++i)
           printf("%d ",ans[i]);
       puts("");
    }
   return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值