传送门
Splay的区间翻转:若要翻转[l, r],将l-1 Splay到根,将r+1 Splay到l-1的右儿子,然后[l, r]就在r+1的左儿子的位置了,给它打上标记,完工!
哦,写的时候一定要注意随时pushdown,以免出错.
数组版
/**************************************************************
Problem: 3223
User: geng4512
Language: C++
Result: Accepted
Time:1868 ms
Memory:4712 kb
****************************************************************/
#include<cstdio>
#define MAXN 200005
int tmp;
inline void Swap(int &a, int &b) { tmp = a; a = b; b = tmp; }
struct node {
int sz, ch[2], f; bool rev;
inline void mt() {
Swap(ch[0], ch[1]);
}
}t[MAXN];
int rt, sz, n, m;
#define Upd(r) {t[r].sz = t[t[r].ch[0]].sz + t[t[r].ch[1]].sz + 1;}
void rot(int x)
{
int y = t[x].f, z = t[y].f;
bool f = (t[y].ch[1] == x);
t[y].ch[f] = t[x].ch[f^1];
if(t[y].ch[f]) t[t[y].ch[f]].f = y;
t[x].ch[f^1] = y; t[y].f = x;
t[x].f = z;
if(z) t[z].ch[t[z].ch[1]==y] = x;
Upd(y);
}
inline void pushdown(int y) {
if(t[y].rev) {t[y].mt(); t[t[y].ch[0]].rev ^= 1; t[t[y].ch[1]].rev ^= 1; t[y].rev = 0;}
}
void Splay(int r, int tp) {
for(int y, z; (y = t[r].f) != tp; rot(r)) {
pushdown(r);
z = t[y].f;
if(z == tp) continue;
if( (t[z].ch[0] == y) == (t[y].ch[0] == r) ) rot(y);
else rot(r);
}
if(!tp) rt = r; Upd(r);
}
int Kth(int x)
{
int y=rt,p;
if(x>t[rt].sz)return 0;
while(1)
{
pushdown(y);
p=t[y].ch[0];
if(t[p].sz+1<x) {
x-=t[p].sz+1;
y=t[y].ch[1];
}
else if(t[p].sz>=x) y=p;
else return y;
}
}
int Build(int l, int r) {
if(l > r) return 0;
int mid = (l + r) >> 1;
t[mid].ch[0] = Build(l, mid-1);
t[mid].ch[1] = Build(mid+1, r);
Upd(mid); t[t[mid].ch[0]].f = t[t[mid].ch[1]].f = mid;
return mid;
}
void Rev(int l, int r) {
int a = Kth(l), b = Kth(r+2);
Splay(a, 0); Splay(b, a); int p = t[b].ch[0];
t[p].rev ^= 1;
}
void print(int x) {
if(x == 0) return;
pushdown(x);
print(t[x].ch[0]);
if(x != 1 && x != n + 2) printf("%d ", x-1);
print(t[x].ch[1]);
}
char c, f;
inline void GET(int &n) {
n = 0; f = 1;
do {c = getchar(); if(c == '-') f = -1;} while(c > '9' || c < '0');
while(c >= '0' && c <= '9') {n=n*10+c-'0';c=getchar();}
n *= f;
}
int main() {
int l, r;
GET(n); GET(m);
rt = Build(1, n+2);
while(m --) {
GET(l); GET(r);
Rev(l, r);
}
print(rt);
}
指针版
/**************************************************************
Problem: 3223
User: geng4512
Language: C++
Result: Accepted
Time:1912 ms
Memory:5492 kb
****************************************************************/
#include<cstdio>
#define MAXN 200005
struct Node {
int sz, v; bool rev; Node *ch[2], *fa;
inline void sw() {Node *tmp = ch[0]; ch[0] = ch[1]; ch[1] = tmp; rev ^=1; }
}t[MAXN], NIL, *nil = &NIL, *rt;
int n, m;
inline void Upd(Node *p) {
p->sz = p->ch[0]->sz + p->ch[1]->sz + 1;
}
inline void pushdown(Node *p) {
if(p->rev) {
p->rev = 0;
if(p->ch[0] != nil) p->ch[0]->sw();
if(p->ch[1] != nil) p->ch[1]->sw();
}
}
Node *Build(int l, int r, Node*fa = nil) {
if(l > r) return nil;
int mid = (l + r) >> 1;
t[mid].v = mid;
t[mid].ch[0] = Build(l, mid-1, &t[mid]);
t[mid].ch[1] = Build(mid+1, r, &t[mid]);
t[mid].fa = fa; Upd(&t[mid]);
return &t[mid];
}
void Rot(Node *x) {
Node *y = x->fa, *z = y->fa;
bool f = (y->ch[1] == x);
pushdown(y); pushdown(x);
y->ch[f] = x->ch[f^1];
if(y->ch[f] != nil) y->ch[f]->fa = y;
x->ch[f^1] = y; y->fa = x;
x->fa = z;
if(z != nil) z->ch[z->ch[1]==y] = x;
Upd(y);
}
char c, f;
inline void GET(int &n) {
n = 0; f = 1;
do {c = getchar(); if(c == '-') f = -1;} while(c > '9' || c < '0');
while(c >= '0' && c <= '9') {n=n*10+c-'0';c=getchar();}
n *= f;
}
void Splay(Node *x, Node *to, Node *&Root = rt) {
for(Node *y, *z; (y = x->fa) != to; Rot(x)) {
z = y->fa;
if(z == to) continue;
if((z->ch[1] == y) == (y->ch[1] == x)) Rot(y);
else Rot(x);
} if(to == nil) Root = x;
Upd(x);
}
Node *Kth(int k, Node *to = nil, Node *&Root = rt) {
Node *y = Root, *z;
if(y->sz < k) return nil;
while(1) {
pushdown(y);
z = y->ch[0];
if(z->sz + 1 < k) {
k -= z->sz + 1;
y = y->ch[1];
} else if(z->sz >= k) y = y->ch[0];
else break;
}
Splay(y, to, Root); return y;
}
inline void Rev(int l, int r) {
Node *a = Kth(l), *b = Kth(r+2, a);
b->ch[0]->sw();
}
void print(Node *p) {
pushdown(p);
if(p->ch[0] != nil) print(p->ch[0]);
if(p->v != 1 && p->v != n+2) printf("%d ", p->v-1);
if(p->ch[1] != nil) print(p->ch[1]);
}
int main() {
//freopen("C:\\1.txt", "r", stdin);
int l, r;
GET(n); GET(m);
rt = Build(1, n+2);
while(m --) {
GET(l); GET(r);
Rev(l, r);
}
print(rt);
}