小记: 这题之前想的简单了, 后来看了样例,发现了自己想法的错误
思路:一开始便发现这题,应该反过来思考的。但是用线段树解决还是有点没想到。
方法是:从后面开始看起,这样计算完它之后,计算后面的值的时候不会影响之前计算过了的结果。相当于无后效性
对每个值 有一个 pos值,那么其所在位置至少是pos+1之后,因为pos值是从0开始的,正常的位置是从1开始的
所以,以pos值建线段树, 目的是在pos+1位置处放下当前的value,而有可能pos+1位置已经被占用了,所以要往后推
这里我们给线段树的每个节点加一个space,代表这一段还有多少个位置可以使用,因为pos+1是从1开始数起的,
所以线段树二分时,左边的空间够的话,就直接进入左边,什么都不用改,而若不够,则要进入右边,但是值要减去左边的space值,
这样求得最后的位置就必然是答案了,而当那个位置确定下来的时候,我们就应该记录下来,开个数组记录即可。
代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <map>
#include <set>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
using namespace std;
#define mst(a,b) memset(a,b,sizeof(a))
#define REP(a,b,c) for(int a = b; a < c; ++a)
#define eps 10e-8
const int MAX_ = 200010;
const int N = 100010;
const int INF = 0x7fffffff;
struct node{
int l, r;
int space;
}tree[MAX_*5];
int ans[MAX_];
int a[MAX_], b[MAX_];
void build(int l, int r, int k)
{
if(l == r){
tree[k].l = l;
tree[k].r = r;
tree[k].space = 1;
return ;
}
int mid = l + (r-l)/2;
tree[k].l = l;
tree[k].r = r;
build(l, mid, k<<1);
build(mid+1, r, (k<<1)|1);
tree[k].space = tree[k<<1].space + tree[(k<<1)|1].space;
}
void insert(int p, int value, int k)
{
if(tree[k].l == tree[k].r){
tree[k].space = 0;
ans[tree[k].l] = value;
return ;
}
if(p <= tree[k<<1].space){
insert(p, value, k<<1);
}
else{
insert(p-tree[k<<1].space, value, (k<<1)|1);
}
tree[k].space = tree[k<<1].space + tree[(k<<1)|1].space;
}
int main(){
int n, m;
while(~scanf("%d", &n)){
REP(i, 0, n){
scanf("%d%d", &a[i], &b[i]);
}
build(0, n-1, 1);
for(int i = n-1; i > -1; --i){
insert(a[i]+1, b[i], 1);
}
printf("%d", ans[0]);
REP(i, 1, n){
printf(" %d",ans[i]);
}
printf("\n");
}
return 0;
}