HDU 3487
需要完成的功能splay的区间翻转与切割粘贴。
每个节点多一个flip域,用于翻转区间,每次只要pushDown就可以了,pushUp只需要维护一个SIZE。值得注意的是findK的时候特别容易忘记pushDown。因此RE了一晚上,浪费时间了。
如果要翻转[a, b] 区间,只要把a - 1旋转到root b + 1,旋转到root的右子树。然后root的右子树的左子树(KEY)就是[a, b]区间了。维护这个区间的flip就可以了
然后是切割功能。与上述相似,切割既要把该子树取下来,然后在进行splay操作,使得要粘贴的地方(c之后)成为KEY就可以了,具体操作,把c - 1旋转到root c旋转到root的右子树,把切割下来的地方link到KEY上即可,不要忘记维护切割下来的子树的pre域,否则接下来的splay操作就是错误的了。
代码如下
/*
* =====================================================================================
*
* Filename: net.cpp
*
* Description: network flow
*
* Version: 1.0
* Created: 08/16/2011 01:53:16 PM
* Revision: none
* Compiler: gcc
*
* Author: ronaflx
* Company: hit-ACM-Group
*
* =====================================================================================
*/
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <iterator>
#include <limits>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <climits>
#include <algorithm>
#include <functional>
#include <numeric>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <bitset>
#include <list>
#include <string>
#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <stdexcept>
#include <utility>
#include <cassert>
#include <complex>
using namespace std;
#define LEFT(i) ((i) << 1)
#define RIGHT(i) (((i) << 1) | 1)
#define MID(i) ((l[i] + r[i]) >> 1)
#define CC(i, v) memset(i, v, sizeof(i))
#define REP(i, l, n) for(int i = l;i < int(n);++i)
#define FOREACH(con, i) for(__typeof(con.begin()) i = con.begin();i != con.end();++i)
#define DEBUG(i) cout << #i << " " << i << endl;
#define lowbit(x) ((x) & (-x))
typedef long long LL;
#define SIZE(x) ((x) ? (x)->size : 0)
#define CENTRE (root->ch[1]->ch[0])
struct node
{
int size;
node* ch[2], *pre;
int v, flip;
node(int v = 0, int size = 1, node* l = 0,
node* r = 0, node* pre = 0)
{
this->v = v;
this->flip = 0;
this->size = size;
this->pre = pre;
ch[0] = l, ch[1] = r;
}
};
node* root;
void pushDown(node*& x)
{
if(x && x->flip)
{
if(x->ch[0]) x->ch[0]->flip ^= 1;
if(x->ch[1]) x->ch[1]->flip ^= 1;
swap(x->ch[0], x->ch[1]);
x->flip = 0;
}
}
void pushUp(node*& x)
{
x->size = SIZE(x->ch[0]) + SIZE(x->ch[1]) + 1;
}
void clear(node*& now)
{
if(now == 0) return;
clear(now->ch[0]);
clear(now->ch[1]);
delete now;
}
void build(int l, int r, node*& now, node* pre)
{
if(l > r) return;
int mid = (l + r) / 2;
now = new node(mid, 1, 0, 0, pre);
build(l, mid - 1, now->ch[0], now);
build(mid + 1, r, now->ch[1], now);
pushUp(now);
}
void rotate(node* x, int type)
{
node *y = x->pre;
pushDown(y);
pushDown(x);
y->ch[!type] = x->ch[type];
if (x->ch[type] != NULL) x->ch[type]->pre = y;
x->pre = y->pre;
if (y->pre != NULL)
{
if (y->pre->ch[0] == y) y->pre->ch[0] = x;
else y->pre->ch[1] = x;
}
x->ch[type] = y, y->pre = x;
if (y == root) root = x; // root 表示整棵树的根结点
pushUp(y);
pushUp(x);
}
void splay(node* x, node* f)
{
pushDown(x);
while(x->pre != f)
{
if (x->pre->pre == f)
{
if (x->pre->ch[0] == x) rotate(x, 1);
else rotate(x, 0);
}
else
{
node *y = x->pre;
node *z = y->pre;
if (z->ch[0] == y)
{
if (y->ch[0] == x) // 一字形旋转
rotate(y, 1), rotate(x, 1);
else // 之字形旋转
rotate(x, 0), rotate(x, 1);
}
else
{
if (y->ch[1] == x) // 一字形旋转
rotate(y, 0), rotate(x, 0);
else // 之字形旋转
rotate(x, 1), rotate(x, 0);
}
}
}
pushUp(x);
}
node* findK(node* now, int K)
{
pushDown(now);
int s = SIZE(now->ch[0]);
if(s + 1 == K)
return now;
else if(s >= K)
return findK(now->ch[0], K);
else
return findK(now->ch[1], K - s - 1);
}
vector<int> ans;
int n, q;
void output(node* now)
{
if(now == 0) return;
pushDown(now);
output(now->ch[0]);
if(now->v != 0 && now->v != n + 1)
ans.push_back(now->v);
output(now->ch[1]);
pushUp(now);
}
void output()
{
ans.clear();
output(root);
for(vector<int>::iterator i = ans.begin();i != ans.end();i++)
printf("%d%c", *i, i + 1 == ans.end() ? '\n' : ' ');
}
void flip(int a, int b)
{
CENTRE->pre = root->ch[1];
node* ll = findK(root, a);
splay(ll, NULL);
node* rr = findK(root, b + 2);
splay(rr, root);
node* now = CENTRE;
now->flip ^= 1;
}
void cut(int a, int b, int c)
{
node* ll = findK(root, a);
splay(ll, NULL);
node* rr = findK(root, b + 2);
splay(rr, root);
node* now = CENTRE;
CENTRE = NULL;
pushUp(root->ch[1]);
pushUp(root);
ll = findK(root, c + 1);
splay(ll, NULL);
rr = findK(root, c + 2);
splay(rr, root);
CENTRE = now;
CENTRE->pre = root->ch[1];
pushUp(root->ch[1]);
pushUp(root);
}
int main()
{
char str[10];
int a, b, c;
root = NULL;
while(scanf("%d %d", &n, &q) == 2 && (n != -1 && q != -1))
{
clear(root);
build(0, n + 1, root, NULL);
REP(i, 0, q)
{
scanf("%s", str);
if(str[0] == 'C')
{
scanf("%d %d %d", &a, &b, &c);
cut(a, b, c);
}
else
{
scanf("%d %d", &a, &b);
flip(a, b);
}
}
output();
}
return 0;
}