题意:
有n个人,第i个人的任务重要度为a[i],良心值为c[i]。
这n个人依次进行排队,当前i-1个人排好队后,第i个人来到队伍末尾,如果站在他前面的人的任务重要度比他的小,第i个人就会说服前面的人与其交换位置,第i人会反复这么做直到他前面的人的任务重要度不小于他,或者他感受到了良心的谴责(即最多交换c[i]次)。你的任务是计算出最后队伍的排列情况。
分析可知,我们需要在后c[i]个数里找到最靠右的大于a[i]的下标。这个可以由Splay维护。
每个节点记录a[i],还有子树中a[i]的最大值。
每次找下标,可以二分下标,然后在Splay中找到这个节点,然后把这个节点Splay到根,返回a[i]的最大值。
再把当前节点插入进去。
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 100005, inf = 0x3f3f3f3f;
int n;
inline int iread() {
int f = 1, x = 0; char ch = getchar();
for(; ch < '0' || ch > '9'; ch = getchar()) f = ch == '-' ? -1 : 1;
for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
return f * x;
}
int son[maxn][2], val[maxn], mx[maxn], pre[maxn], size[maxn], id[maxn];
int tot1, tot2, sta[maxn], root;
inline void newnode(int &x, int c, int f, int p) {
x = tot2 ? sta[tot2--] : ++tot1;
son[x][0] = son[x][1] = 0;
pre[x] = f;
size[x] = 1;
val[x] = mx[x] = c;
id[x] = p;
}
inline void pushup(int x) {
int l = son[x][0], r = son[x][1];
size[x] = size[l] + size[r] + 1;
mx[x] = max(max(mx[son[x][0]], mx[son[x][1]]), val[x]);
}
inline void init() {
tot1 = tot2 = root = 0;
son[0][0] = son[0][1] = val[0] = mx[0] = pre[0] = size[0] = id[0] = 0;
newnode(root, inf, root, 0);
newnode(son[root][1], 0, root, 0);
pushup(son[root][1]); pushup(root);
}
inline void rotate(int x) {
int y = pre[x], z = pre[y], type = son[y][1] == x;
pre[son[y][type] = son[x][!type]] = y;
pre[x] = z;
if(z) son[z][son[z][1] == y] = x;
pre[son[x][!type] = y] = x;
pushup(y); pushup(x);
}
inline void splay(int x, int goal) {
while(pre[x] != goal) {
int y = pre[x], z = pre[y];
if(z == goal) rotate(x);
else if(son[z][0] == y ^ son[y][0] == x) rotate(x), rotate(x);
else rotate(y), rotate(x);
}
if(goal == 0) root = x;
}
inline int find(int k) {
int x = root;
while(k != size[son[x][0]] + 1)
if(k <= size[son[x][0]]) x = son[x][0];
else k -= size[son[x][0]] + 1, x = son[x][1];
return x;
}
inline int getmax(int x) {
int l = find(x);
splay(l, 0);
return max(mx[son[root][1]], val[root]);
}
inline void insert(int pos, int c, int idx) {
int l = find(pos - 1), r = find(pos);
splay(l, 0); splay(r, root);
newnode(son[son[root][1]][0], c, son[root][1], idx);
pushup(son[root][1]); pushup(root);
}
void dfs(int x) {
if(x == 0) return;
dfs(son[x][0]);
if(id[x]) printf("%d ", id[x]);
dfs(son[x][1]);
}
int main() {
n = iread();
init();
for(int i = 1; i <= n; i++) {
int a = iread(), c = iread();
int l = 1, r = i + 1;
while(l <= r) {
int mid = l + r >> 1;
if(getmax(mid) > a) l = mid + 1;
else r = mid - 1;
}
if(i - l + 1 > c) l = i - c + 1;
insert(l, a, i);
}
dfs(root);
return 0;
}