poj 2828(线段树:单点插入,区间查询)

排队买票,但是 中途 出现插队情况,比如 0 123,代表值为123的人 插入到 0 的位置,如果后面 出现 0 456,那么新的 0的位置就是 456,123就变成是 1的位置了

观察发现,最后一个插入到该位置的人位置是固定的,那么我们可以从后面进行插入操作,pos val 代表val要插入到pos位置,那么就是说 pos 前面要留出 pos个位置,

因为 是从 0 开始的。

线段树 :res 记录 该区间 目前还剩 res个空位,每一次 query即插入的时候 ,如果 该节点左儿子 res >=pos,那么只要在左儿子找就可以了

否则 要在右儿子中 找 ,此时 pos 改为 pos-左儿子res。。

 

#include <cstdio>
#include <iostream>
#include <algorithm>
#define lson L , m , rt << 1
#define rson m + 1 , R , rt << 1 | 1
using namespace std;
const int maxn = 240000;
struct Node
{
    int L,R;
    int sum;
}tree[maxn*4];
int p[maxn],val[maxn];
int n;
void builttree(int L,int R,int rt)
{
    tree[rt].L=L;
    tree[rt].R=R;
    tree[rt].sum=R-L+1;
    if(L==R)
    return ;
    int m=(L+R)/2;
    builttree(lson);
    builttree(rson);
}
int ans[maxn];
void Query(int rt,int pos,int val)
{
    tree[rt].sum--;
    if(tree[rt].L==tree[rt].R)
    {
      ans[tree[rt].L]=val;
      return ;
    }
    int m=(tree[rt].L+tree[rt].R)/2;
    if(tree[rt*2].sum>=pos)
      Query(rt*2,pos,val);//左孩子可以容下则进左孩子
    else
      Query(rt*2+1,pos-tree[rt*2].sum,val);//左孩子已满
}
int main()
{
  while(scanf("%d",&n)!=EOF)
  {
      for(int i=1;i<=n;i++)
        scanf("%d%d",&p[i],&val[i]);
      builttree(1,n,1);
      for(int i=n;i>=1;i--)
      {
          Query(1,p[i]+1,val[i]);
      }
      for(int i=1;i<=n;i++)
      {
          if(i==1)
          printf("%d",ans[i]);
          else
          printf(" %d",ans[i]);
      }
      printf("\n");
  }
  return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值