艰难地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; }