# BZOJ 3223: Tyvj 1729 文艺平衡树

/*
BZOJ 3223: Tyvj 1729 文艺平衡树

splay 区间翻转

每次翻转区间[l,r]都是把l旋到根节点上， r旋到根节点的右节点上
那么要修改的区间就是根节点的右孩子的左子树
然后打标记。。
之后每次查到时就下放标记

原区间为1 ~ N
增加两个哨兵节点 0 和 N + 1， 避免翻转1~N的区间产生麻烦

*/
#include <cstdio>

#define Max 200009

inline int swap (int &a, int &b)
{
int now = a;
a = b;
b = now;
}

{
now = 0;
register char word = getchar ();
while (word < '0' || word > '9')
word = getchar ();
while (word >= '0' && word <= '9')
{
now = now * 10 + word - '0';
word = getchar ();
}
}

int value[Max];
int N, M;

class Splay_Tree_Type
{
private :

struct Splay_Tree_Date
{
int size;
int key;
int father;
int child[2];
int Flandre;
}
tree[Max];

inline int Get_Son (int now)
{
return tree[tree[now].father].child[1] == now;
}

inline void Update (int now)
{
tree[now].size = 1;
if (tree[now].child[0])
tree[now].size += tree[tree[now].child[0]].size;
if (tree[now].child[1])
tree[now].size += tree[tree[now].child[1]].size;
}

int Root;
int Count;

inline void Down (int now)
{
tree[now].Flandre = 0;
swap (tree[now].child[0], tree[now].child[1]);
if (tree[now].child[0])
tree[tree[now].child[0]].Flandre ^= 1;
if (tree[now].child[1])
tree[tree[now].child[1]].Flandre ^= 1;
}

inline void Rotate (int now)
{
int father = tree[now].father;
int Grand = tree[father].father;
int pos = Get_Son (now);
if (tree[father].Flandre && father) // 注意这里标记下放的次序
Down (father);
if (tree[now].Flandre && now)
Down (now);
tree[father].child[pos] = tree[now].child[pos ^ 1];
tree[tree[father].child[pos]].father = father;
tree[now].child[pos ^ 1] =  father;
tree[father].father = now;
tree[now].father = Grand;
if (Grand)
tree[Grand].child[tree[Grand].child[1] == father] = now;
Update (father);
Update (now);
}

void Get_Answer (int now) // 把整棵树进行中序遍历后的序列就是答案
{
if (tree[now].Flandre)
Down (now);
if (tree[now].child[0])
if (tree[now].child[1])
}

int Build (int l, int r, int father)
{
int now = l + r >> 1;
tree[now].father = father;
tree[now].key = value[now];
if (now > l)
tree[now].child[0] = Build (l, now - 1, now);
if (now < r)
tree[now].child[1] = Build (now + 1, r, now);
Update (now);
return now;
}

public :

void Prepare ()
{
Root = 1;
Root = Build(1, N + 2, 0);
}

void Splay (int now, int to)
{
for (int father; (father = tree[now].father) != to; Rotate (now))
if (tree[father].father != to)
Rotate (Get_Son (now) == Get_Son (father) ? father : now);
if (!to)
Root = now;
}

int Get_Pos (int x)
{
int now = Root;
for (; ; )
{
if (tree[now].Flandre)
Down (now);
if (x <= tree[tree[now].child[0]].size)
now = tree[now].child[0];
else
{
x -= tree[tree[now].child[0]].size + 1;
if (!x)
return now;
now = tree[now].child[1];
}
}
}

inline void Print ()
{
for (int i = 1; i <= N; i++)
printf ("%d ", Answer[i + 1]);
}

inline void Hit_flag ()
{
tree[tree[tree[Root].child[1]].child[0]].Flandre ^= 1;
}
};

Splay_Tree_Type Make;

int main (int argc, char *argv[])
{
read (M); // 0号点和 N+1 号点代表是哨兵节点
for (int i = 1; i <= N + 2; i++) // 预先处理出值
value[i] = i - 1;
int l, r;
Make.Prepare ();  // splay建树， 要建满二叉树
for (; M--; )
{
r += 2;
l = Make.Get_Pos (l); // 找到在树中对应的位置
r = Make.Get_Pos (r);
Make.Splay (l, 0);
Make.Splay (r, l);
Make.Hit_flag ();  // 打上标记
}
Make.Print ();
return 0;
}

myj 吊打我Orz，xxy 捆起来打我Orz，myl 文化课上天Orz， lrh 姿势水平敲高Orz， hkd 特别胖Orz%%%，cys 智商感人Orz，syl zz专业Orz，我没有学上， 我们未来一片光明
posted @ 2017-05-20 16:09  ZlycerQan  阅读(125)  评论(0编辑  收藏  举报