每次寫樹的時候都腦殼疼。
對大佬們這就是一道水題,可是對自己着實有點不好解決。憋了兩天照着模板分析分析不出來,splay tree思想很精彩,實現很精妙,再加上這道題還有延遲標記,雖然過程有點難頂,但最後收穫頗豐
這道題要注意幾個細節:
- splay tree時時記住maintain(本模板就是pushup)
- 因爲這道題使用了延遲標記,所以一定要明晰什麼時候pushdown,基本上,除了建樹和逆轉無關以外,其他的部分都涉及到了pushdown的部分,因爲,任何的旋轉修改樹的結構,或是查詢的時候都涉及到了當前樹節點對順序(保守方法就是見到就Pushdown,一般這裏的時間複雜度差異也不會特別大,機器那一點時間在這種短時間評測換來編碼時間並減少出錯率是值得的,但是自己練習的時候還是訓練自己弄清楚爲好)
- 具體實現的時候,建立樹時特意加入兩個哨兵節點分別放在數列的一頭一尾,看模板的時候開始一直沒有理解,實現到後面觀察如何獲取結果的時候方纔恍然大悟
- 每次逆轉操作,除了lazy tag之外,還借用配合了splay操作實現對於一段區間的操作,這是種非常值得關注的trick
#include <iostream>
#include <algorithm>
#include <queue>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <stack>
#include <map>
#include <set>
#include <deque>
using namespace std;
const int maxn= 1e5+5;
struct Node;
Node *null;
struct Node
{
Node *ch[2], *fa;
int size, rev;
void clear()
{
if (this== null){
return;
}
ch[0]= ch[1]= fa= null;
size= 1;
rev= 0;
}
void pushUp()
{
if (this== null){
return;
}
size= ch[0]->size+ch[1]->size+1;
}
void setc(Node *p, int d)
{
if (this== null){
return;
}
ch[d]= p;
p->fa= this;
}
int d()
{
return fa->ch[1]== this;
}
void updateRev()
{
if (this== null){
return;
}
swap(ch[0], ch[1]);
rev^= 1;
}
void pushDown()
{
if (this== null){
return;
}
if (rev){
ch[0]->updateRev();
ch[1]->updateRev();
rev= 0;
}
}
};
Node pool[maxn], *tail, *root;
Node *node[maxn];
int a[maxn], b[maxn];
void Rotate(Node *x)
{
if (x->fa== null){
return;
}
Node *f= x->fa, *ff= x->fa->fa;
f->pushDown();
x->pushDown();
int c= x->d(), cc= f->d();
f->setc(x->ch[!c], c);
x->setc(f, !c);
if (ff->ch[cc]== f){
ff->setc(x, cc);
}
else{
x->fa= ff;
}
f->pushUp();
}
void Splay(Node *&root, Node *x, Node *goal)
{
while (x->fa!= goal){
if (x->fa->fa== goal){
Rotate(x);
}
else{
x->fa->fa->pushDown();
x->fa->pushDown();
x->pushDown();
int c= x->d(), cc= x->fa->d();
c== cc ? Rotate(x->fa) : Rotate(x);
Rotate(x);
}
}
x->pushUp();
if (null== goal){
root= x;
}
}
Node *get_kth(Node *r, int k)
{
Node *x= r;
x->pushDown();
while (k!= x->ch[0]->size+1){
if (k<= x->ch[0]->size){
x= x->ch[0];
}
else{
k-= x->ch[0]->size+1;
x= x->ch[1];
}
x->pushDown();
}
return x;
}
void Build(Node *&x, int l, int r, Node *fa)
{
if (l> r){
return;
}
int mid= (l+r)>>1;
x= tail++;
x->clear();
x->fa= fa;
node[mid]= x;
Build(x->ch[0], l, mid-1, x);
Build(x->ch[1], mid+1, r, x);
x->pushUp();
}
void Init(int n)
{
tail= pool;
null= tail++;
null->ch[0]= null->ch[1]= null->fa= null;
null->size= null->rev= 0;
Node *p= tail++;
p->clear();
root= p;
p= tail++;
p->clear();
root->setc(p, 1);
Build(p->ch[0], 1, n, p);
p->pushUp();
root->pushUp();
}
bool cmp(int i, int j)
{
if (a[i]!= a[j]){
return a[i]< a[j];
}
return i< j;
}
int main(int argc, char const *argv[])
{
int n;
while (1== scanf("%d", &n) && n){
for (int i= 1; i<= n; ++i){
scanf("%d", a+i);
b[i]= i;
}
Init(n);
sort(b+1, b+1+n, cmp);
for (int i= 1; i<= n; ++i){
Splay(root, node[b[i]], null);
int sz= root->ch[0]->size;
printf("%d", sz);
if (i== n){
putchar('\n');
}
else{
putchar(' ');
}
Splay(root, get_kth(root, i), null);
Splay(root, get_kth(root, sz+2), root);
root->ch[1]->ch[0]->updateRev();
}
}
return 0;
}