小記: 這題之前想的簡單了, 後來看了樣例,發現了自己想法的錯誤
思路:一開始便發現這題,應該反過來思考的。但是用線段樹解決還是有點沒想到。
方法是:從後面開始看起,這樣計算完它之後,計算後面的值的時候不會影響之前計算過了的結果。相當於無後效性
對每個值 有一個 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;
}