题目链接:点我啊╭(╯^╰)╮
题目大意:
插队问题,每次给出 p o s pos pos 和 v a l val val,将 v a l val val 插入到 p o s pos pos 的后面,保证每次的 p o s pos pos 前都有数字,求最后的序列
解题思路:
先离线处理,这样倒过来后,每次插入的位置都是确定的,问题在于如何插入
这里就可以用到线段树的单点更新,插入的时候如果左子树满了,就插入到右子树中,这一点类似于
P
O
J
POJ
POJ
2886
2886
2886,最终就实现了
l
o
g
(
n
)
log(n)
log(n)的单点插入
代码思路:
线段树 + 离线处理即可,在更新的时候注意插入的位置
核心:线段树的好题,对单点更新有了新的理解
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pushup(rt) t[rt] = t[rt<<1] + t[rt<<1|1];
const int maxn = 200000+10;
ll t[maxn<<2],lazy[maxn<<2],a[maxn][5];
void build(int l,int r,int rt) {
lazy[rt] = 0;
if(l==r) {
t[rt] = 1;
return ;
}
int m = (l+r)>>1;
build(lson);
build(rson);
pushup(rt);
}
void update(int pos,int C,int l,int r,int rt) {
if(l==r) {
t[rt]=0;
lazy[rt] = C;
return ;
}
int m = (l+r)>>1;
if(pos<t[rt<<1]) update(pos,C,lson);
else update(pos-t[rt<<1],C,rson);
pushup(rt);
}
void printf_ans(int l,int r,int rt){
if(l==r){
printf("%d ", lazy[rt]);
return ;
}
int m = (l+r)>>1;
printf_ans(lson);
printf_ans(rson);
}
int main(){
int n;
while(~scanf("%d", &n)){
build(1,n,1);
for(int i=1; i<=n; i++) scanf("%d %d", &a[i][0], &a[i][1]);
for(int i=n; i>=1; i--) update(a[i][0],a[i][1],1,n,1);
printf_ans(1,n,1);
printf("\n");
}
}