题目大意:给出一个序列,给出一种排序方式,模拟这种排序方式排序,并输出每次找到的节点的位置。
思路:它让你做什么你就做什么,无非就是个Reverse,很简单。注意一下排序的时候权值相等的情况就行了。
CODE:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 100010
#define INF 0x3f3f3f3f
using namespace std;
struct SplayTree{
SplayTree *son[2],*father;
bool reverse;
int size;
SplayTree();
bool Check() {
return father->son[1] == this;
}
void Combine(SplayTree *a,bool dir) {
a->father = this;
son[dir] = a;
}
void Reverse() {
reverse ^= 1;
swap(son[0],son[1]);
}
void PushUp() {
size = son[0]->size + son[1]->size + 1;
}
void PushDown() {
if(reverse) {
son[0]->Reverse();
son[1]->Reverse();
reverse = false;
}
}
}none,*nil = &none,*root;
SplayTree:: SplayTree() {
son[0] = son[1] = nil;
reverse = false;
size = 1;
}
struct Complex{
int val,pos;
SplayTree *a;
bool operator <(const Complex &a)const {
if(val == a.val) return pos < a.pos;
return val < a.val;
}
void Read(int p) {
scanf("%d",&val);
pos = p;
}
}src[MAX];
int cnt;
void Pretreatment()
{
nil->size = 0;
nil->son[0] = nil->son[1] = nil->father = nil;
}
SplayTree *BuildTree(int l,int r)
{
if(l > r) return nil;
int mid = (l + r) >> 1;
SplayTree *re = new SplayTree();
src[mid].a = re;
re->Combine(BuildTree(l,mid - 1),false);
re->Combine(BuildTree(mid + 1,r),true);
re->PushUp();
return re;
}
inline void Rotate(SplayTree *a,bool dir)
{
SplayTree *f = a->father;
f->PushDown(); a->PushDown();
f->son[!dir] = a->son[dir];
f->son[!dir]->father = f;
a->son[dir] = f;
a->father = f->father;
f->father->son[f->Check()] = a;
f->father = a;
f->PushUp();
if(f == root) root = a;
}
inline void Splay(SplayTree *a,SplayTree *aim)
{
while(a->father != aim) {
if(a->father->father == aim)
Rotate(a,!a->Check());
else if(!a->father->Check()) {
if(!a->Check())
Rotate(a->father,true),Rotate(a,true);
else Rotate(a,false),Rotate(a,true);
}
else {
if(a->Check())
Rotate(a->father,false),Rotate(a,false);
else Rotate(a,true),Rotate(a,false);
}
}
a->PushUp();
}
SplayTree *Find(SplayTree *a,int k)
{
a->PushDown();
if(a->son[0]->size >= k) return Find(a->son[0],k);
k -= a->son[0]->size;
if(k == 1) return a;
return Find(a->son[1],k - 1);
}
inline void SplaySeg(int x,int y)
{
x++,y++;
Splay(Find(root,x - 1),nil);
Splay(Find(root,y + 1),root);
}
int main()
{
cin >> cnt;
Pretreatment();
for(int i = 1; i <= cnt; ++i)
src[i].Read(i);
src[0].val = src[cnt + 1].val = INF;
root = BuildTree(0,cnt + 1);
root->father = nil;
sort(src + 1,src + cnt + 1);
for(int i = 1; i <= cnt; ++i) {
Splay(src[i].a,nil);
printf("%d%c",root->son[0]->size," \n"[i == cnt]);
SplaySeg(i,root->son[0]->size);
root->son[1]->son[0]->Reverse();
}
return 0;
}