标签:bzoj bzoj1493 splay noi2007 伸展树
题目大意:有一个很长的带颜色的项链,要求你快速的维护一种数据结构,他可以:
1.把序列的后k个放在前面。
2.将区间2~cnt的珠子翻转。
3.将位置i和位置j的珠子互换。
4.将区间i到j染色成k
5.输出整个序列的颜色块的个数
6.输出从i到j的颜色块的个数。
思路:Splay。有些不好处理的是要时刻想着这是一个环,所以所有的计算颜色块的个数的时候要考虑收尾的颜色是否相同。还有从序列的尾部到转一圈回去的情况。
就因为这个题我的代码有个小小小小的问题,花了仨小时的时间带着数据才把错找到。。简直不知道说些什么好。。啊啊啊啊以后写题一定要细致啊!!!
CODE:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 500010
using namespace std;
struct Complex{
int col,cnt_col,l_col,r_col;
int size;
Complex *son[2],*father;
bool reverse,change;
int change_into;
void Combine(Complex *a,bool dir) {
son[dir] = a;
a->father = this;
}
bool Check() {
return father->son[1] == this;
}
void Reverse();
void Paint(int val);
void PushUp();
void PushDown();
}*nil = new Complex(),*root;
int cnt,cols,asks;
int src[MAX];
char cmd[10];
void Pretreatment();
inline Complex *NewComplex(int val);
Complex *BuildTree(int l,int r);
Complex *Kth(Complex *a,int k);
inline void Rotate(Complex *a,bool dir);
inline void Splay(Complex *a,Complex *aim);
inline void SplaySeg(int x,int y);
int main()
{
Pretreatment();
cin >> cnt >> asks;
for(int i = 1;i <= cnt; ++i)
scanf("%d",&src[i]);
root = BuildTree(0,cnt + 1);
root->father = nil;
cin >> asks;
for(int x,y,z,i = 1;i <= asks; ++i) {
scanf("%s",cmd);
if(cmd[0] == 'R') {
scanf("%d",&x);
SplaySeg(cnt - x + 1,cnt);
Complex *temp = root->son[1]->son[0];
temp->father = nil;
root->son[1]->son[0] = nil;
root->son[1]->PushUp(),root->PushUp();
Splay(Kth(root,1),nil);
Splay(Kth(root,2),root);
root->son[1]->Combine(temp,false);
}
else if(cmd[0] == 'F') {
SplaySeg(2,cnt);
root->son[1]->son[0]->Reverse();
}
else if(cmd[0] == 'S') {
scanf("%d%d",&x,&y);
if(x == y) continue;
if(x > y) swap(x,y);
Splay(Kth(root,x + 1),nil);
Splay(Kth(root,y + 1),root);
int temp = root->son[1]->col;
root->son[1]->col = root->col;
root->son[1]->PushUp(),root->PushUp();
root->col = temp;
}
else if(cmd[0] == 'P') {
scanf("%d%d%d",&x,&y,&z);
if(y >= x) {
SplaySeg(x,y);
root->son[1]->son[0]->Paint(z);
}
else {
SplaySeg(x,cnt);
root->son[1]->son[0]->Paint(z);
root->son[1]->PushUp(),root->PushUp();
SplaySeg(1,y);
root->son[1]->son[0]->Paint(z);
}
}
else if(cmd[0] == 'C' && cmd[1] == '\0') {
SplaySeg(1,cnt);
int ans = root->son[1]->son[0]->cnt_col;
ans -= (root->son[1]->son[0]->l_col == root->son[1]->son[0]->r_col);
if(!ans) ++ans;
printf("%d\n",ans);
continue;
}
else {
scanf("%d%d",&x,&y);
if(y >= x) {
SplaySeg(x,y);
printf("%d\n",root->son[1]->son[0]->cnt_col);
}
else {
int ans = 0;
SplaySeg(x,cnt);
ans = root->son[1]->son[0]->cnt_col;
SplaySeg(1,y);
ans += root->son[1]->son[0]->cnt_col;
SplaySeg(1,cnt);
ans -= (root->son[1]->son[0]->l_col == root->son[1]->son[0]->r_col);
printf("%d\n",ans);
}
continue;
}
root->son[1]->PushUp(),root->PushUp();
}
return 0;
}
void Complex:: Reverse()
{
if(!col) return ;
reverse ^= 1;
swap(son[0],son[1]);
swap(l_col,r_col);
}
void Complex:: Paint(int val)
{
if(!col) return ;
change = true;
change_into = val;
l_col = r_col = col = val;
cnt_col = 1;
}
void Complex:: PushUp()
{
if(this == nil) return ;
size = son[0]->size + son[1]->size + 1;
if(!col) return ;
cnt_col = 1;
l_col = r_col = col;
if(son[0]->col) {
cnt_col += son[0]->cnt_col - (son[0]->r_col == col);
l_col = son[0]->l_col;
}
if(son[1]->col) {
cnt_col += son[1]->cnt_col - (son[1]->l_col == col);
r_col = son[1]->r_col;
}
}
void Complex:: PushDown()
{
if(this == nil) return ;
if(reverse) {
son[0]->Reverse();
son[1]->Reverse();
reverse = false;
}
if(change) {
son[0]->Paint(change_into);
son[1]->Paint(change_into);
change = false;
}
}
void Pretreatment()
{
nil->size = 0;
nil->col = nil->l_col = nil->r_col = 0;
nil->cnt_col = 0;
nil->father = nil->son[0] = nil->son[1] = nil;
}
inline Complex *NewComplex(int val)
{
Complex *re = new Complex();
re->col = re->l_col = re->r_col = val;
re->size = 1;
if(val) re->cnt_col = 1;
re->son[0] = re->son[1] = nil;
return re;
}
Complex *BuildTree(int l,int r)
{
if(l > r) return nil;
int mid = (l + r) >> 1;
Complex *re = NewComplex(src[mid]);
re->Combine(BuildTree(l,mid - 1),false);
re->Combine(BuildTree(mid + 1,r),true);
re->PushUp();
return re;
}
Complex *Kth(Complex *a,int k)
{
a->PushDown();
if(a->son[0]->size >= k) return Kth(a->son[0],k);
k -= a->son[0]->size;
if(k == 1) return a;
return Kth(a->son[1],k - 1);
}
inline void Rotate(Complex *a,bool dir)
{
Complex *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(root == f) root = a;
}
inline void Splay(Complex *a,Complex *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();
}
inline void SplaySeg(int x,int y)
{
x++,y++;
Splay(Kth(root,x - 1),nil);
Splay(Kth(root,y + 1),root);
}
标签:bzoj bzoj1493 splay noi2007 伸展树
原文地址:http://blog.csdn.net/jiangyuze831/article/details/39552621