Description
一些人在排队买车票,假设每个人都有不同的买票紧急程度,如果某个人的紧急程度比排在他前一个的人的紧急程度更大,则这个人可以和前一个人调换位置,并且假设每个人都有一个耐心值,若某人的耐心值为x,则他最多可以向前调换x次,当然前提是他之前x个人的紧急程度都比他小,若遇到前面一个人紧急程度比他大的他将停止往前调换。现假设有N个人,按顺序一个个进入队列,并且每进去一个人立即按照紧急程度和其耐心值向前进行调换,调换停止后下一个人才进入队列。给出这N个人的紧急程度和耐心值,问最终的排队情况。
Input
第一行输入一个整数T,表示数据组数。接下来T组数据,对于每组数据,第一行输入一个整数n (1<=n<=10^5),接下来第2到n+1行每行输入两个整数a[i],c[i] (1<=a[i]<=n,0<=c[i]<=n),分别表示第i个人的紧急程度在n个人种排第几及其耐心值,a[i]越大表示紧急程度越大。
Output
对于每组数据,请输出一行n个数,以一个空格隔开,表示最终队列的排队情况,第i个数表示最终排在第i个位置的人是第几个进入队列的。
Sample Input
1
5
2 3
1 4
4 3
3 1
5 2
Sample Output
3 1 5 4 2
Source
FOJ有奖月赛-2012年11月
直接用splay去模拟操作过程,对于一个人,找到其耐心能到的最大位置,然后在这段区间里找最后一个优先级大于他的人,把这个人插在他后面。
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int mod = 1e9 + 7;
const int maxn = 2e5 + 10;
const int low(int x){ return x&-x; }
int T, n, x, y, flag;
struct Splays
{
const static int maxn = 2e5 + 10; //节点个数
const static int INF = 0x7FFFFFFF; //int最大值
int ch[maxn][2], F[maxn], sz; //左右儿子,父亲节点和节点总个数
int S[maxn], M[maxn], A[maxn];
int Node(int f, int a) { S[sz] = 1; A[sz] = M[sz] = a; ch[sz][0] = ch[sz][1] = 0; F[sz] = f; return sz++; }//申请一个新节点
void clear(){ sz = 1; S[0] = ch[0][0] = ch[0][1] = F[0] = 0; M[0] = INF; }//清空操作
void Count(int x)
{
M[x] = min(A[x], min(M[ch[x][0]], M[ch[x][1]]));
S[x] = S[ch[x][0]] + S[ch[x][1]] + 1;
}
void rotate(int x, int k)
{
int y = F[x]; ch[y][!k] = ch[x][k]; F[ch[x][k]] = y;
if (F[y]) ch[F[y]][y == ch[F[y]][1]] = x;
F[x] = F[y]; F[y] = x; ch[x][k] = y;
M[x] = M[y]; S[x] = S[y]; Count(y);
}
void Splay(int x, int r)
{
for (int fa = F[r]; F[x] != fa;)
{
if (F[F[x]] == fa) { rotate(x, x == ch[F[x]][0]); return; }
int y = x == ch[F[x]][0], z = F[x] == ch[F[F[x]]][0];
y^z ? (rotate(x, y), rotate(x, z)) : (rotate(F[x], z), rotate(x, y));
}
}
void build(int &x)
{
x = Node(0, 0);
ch[x][1] = Node(x, INF);
}
void insert(int &x, int y, int z)
{
for (int i = x; i;)
{
if (y <= S[ch[i][0]]) { i = ch[i][0]; continue; }
if (y == S[ch[i][0]] + 1) { Splay(i, x); x = i; break; }
y -= S[ch[i][0]] + 1; i = ch[i][1];
}
for (int i = ch[x][1]; i; i = ch[i][1])
{
if (!ch[i][1]) { Splay(i, ch[x][1]); break; }
}
int now = ch[ch[x][1]][0];
S[x]++; S[ch[x][1]]++;
M[x] = min(M[x], z); M[ch[x][1]] = min(M[ch[x][1]], z);
if (!now){ ch[ch[x][1]][0] = Node(ch[x][1], z); return; }
for (int i = ch[ch[x][1]][0]; i;)
{
S[i]++; M[i] = min(z, M[i]);
if (M[ch[i][1]] < z) { i = ch[i][1]; continue; }
if (A[i] < z)
{
if (ch[i][1]) { i = ch[i][1]; continue; }
else { now = ch[i][1] = Node(i, z); Splay(ch[i][1], x); break; }
}
else
{
if (ch[i][0]) { i = ch[i][0]; continue; }
else { now = ch[i][0] = Node(i, z); Splay(ch[i][0], x); break; }
}
}
x = now;
}
void dfs(int x)
{
if (!x) return;
dfs(ch[x][0]);
if (x>2)
{
if (flag) printf(" "); else flag = 1;
printf("%d", x - 2);
}
dfs(ch[x][1]);
}
}solve;
int main()
{
scanf("%d", &T);
while (T--)
{
int root = 0; solve.clear();
solve.build(root);
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
scanf("%d%d", &x, &y);
solve.insert(root, max(1, i - y), n + 1 - x);
}
flag = 0; solve.dfs(root);
printf("\n");
}
return 0;
}