艰难地A了这个题目。。。还是代码能力太弱了。
主要思想:位置可以变换。。但是某个位置对应的内存地址是不会变的,沿着某个节点的父亲往上暴力统计就能知道他现在在什么位置了,注意先pushDown
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <iostream>
#include <map>
#pragma warning(disable:4996)
#define _CRT_SECURE_NO_WARNINGS
using namespace std;
const int N = 100010;
const int inf = 2000000000;
struct Node{
Node *l, *r, *p;
int key, aux, size;
bool lazy;
}node[N];
typedef Node * Tnode;
Tnode root, nill, stack[N];
int tot;
Tnode pos[N];
int n, q, top;
struct Height
{
int id, h;
bool operator < (const Height &s1) const{
if (h != s1.h) return h < s1.h;
else return id < s1.id;
}
}arr[N];
inline void PushDown(Tnode &o){
if (o == nill) return;
if (o->lazy){
swap(o->l->l, o->l->r);
swap(o->r->l, o->r->r);
o->l->lazy ^= 1;
o->r->lazy ^= 1;
o->lazy = false;
}
}
inline void PushUp(Tnode &o){
if (o == nill) return;
o->size = o->l->size + o->r->size + 1;
o->l->p = o->r->p = o;
}
inline void Split(Tnode o, Tnode &a, Tnode &b, int num){
//printf("o:%d a:%d b:%d\n", o->key, a->key, b->key);
if (o->size == num) { a = o, b = nill; return; }
else if (num == 0){ a = nill, b = o; return; }
else{
PushDown(o);
// printf("o->l:%d\n", o->l - node);
if (o->l->size >= num){
b = o;
Split(o->l, a, b->l, num);
PushUp(b);
}
else{
a = o;
Split(o->r, a->r, b, num - 1 - o->l->size);
PushUp(a);
}
}
}
inline void Merge(Tnode &o, Tnode a, Tnode b){
if (a == nill) { o = b; return; }
else if (b == nill) { o = a; return; }
else {
if (a->aux <= b->aux){
PushDown(a);
o = a;
Merge(o->r, a->r, b);
}
else{
PushDown(b);
o = b;
Merge(o->l, a, b->l);
}
PushUp(o);
}
}
inline void Build(){
tot = 0;
nill = &node[tot++];
nill->aux = inf;
nill->size = nill->key = 0;
nill->l = nill->r = nill->p = nill;
nill->lazy = false;
root = nill;
}
Tnode NewNode(int key){
Tnode ret = &node[tot++];
ret->key = key;
ret->size = 1;
ret->aux = ((rand() << 15) + rand()) % inf;
ret->l = ret->r = ret->p = nill;
ret->lazy = false;
return ret;
}
inline void Find(Tnode now){
if (now == nill) return;
//printf("key:%d\n", now->key);
stack[++top] = now;
Find(now->p);
}
inline void Update(int l, int r){
// printf("l:%d r:%d\n", l, r);
Tnode a, b, c;
Split(root, a, b, l - 1);
// printf("a:%d b:%d \n", a ->size, b ->size );
Split(b, b, c, r - l + 1);
// printf("a:%d b:%d c:%d\n", a - node, b - node, c - node);
swap(b->l, b->r);
b->lazy ^= 1;
Merge(b, b, c);
Merge(root, a, b);
}
inline int FindKth(Tnode now){
top = 0;
Find(now);
int ret = 0;
while (top){
now = stack[top--];
PushDown(now);
if (top > 0 && now->r == stack[top]) ret += now->l->size + 1;
}
ret += now->l->size + 1;
return ret;
}
inline void dfs(Tnode now){
if (now == nill) return;
dfs(now->l);
printf("%d", now->key);
dfs(now->r);
}
int main(){
#ifdef ACM
freopen("input.txt", "r", stdin);
#endif
//freopen("output.txt", "w", stdout);
while (scanf("%d", &n) != EOF){
Build();
for (int i = 1; i <= n; i++){
scanf("%d", &arr[i].h);
arr[i].id = i;
pos[i] = NewNode(arr[i].h);
Merge(root, root, pos[i]);
}
/*dfs(root);
puts("");*/
sort(arr + 1, arr + 1 + n);
for (int i = 1; i <= n; i++){
int kth = FindKth(pos[arr[i].id]);
printf("%d%c", kth, i == n ? '\n' : ' ');
//printf("i:%d kth:%d\n", arr[i].h, kth);
Update(i, kth);
//printf("root:%d\n", root - node);
/*dfs(root);
puts("");*/
}
}
return 0;
}