这题是2012天津网络赛的题
比赛的时候还不会splay tree当时是用双向链表模拟过掉的
赛后听说这题是裸的splay tree, 现在就拿来练练splay tree, 还真的是超裸的splay tree, 就是结点太多, 最后输出的时候dfs会爆栈, 最后直接手写栈= 0 = , 结果pushdown函数忘记加了, 一直WA, 调了半天才发现, 弱爆了orz
这题操作很多, 不过都不难就不详细讲了, 直接贴代码了, 这里把两种代码都贴上
splay tree
#include <cstdio>
#include <stack>
#include <algorithm>
using namespace std;
const int N = 1000007;
#define KT ch[ch[root][1]][0]
int fa[N], ch[N][2], sz[N], root, tot;
bool rev[N];
int num[N];
inline void pushup(int x)
{
sz[x] = 1 + sz[ch[x][0]] + sz[ch[x][1]];
}
inline void pushdown(int x)
{
if(rev[x])
{
rev[ch[x][0]] ^= 1;
rev[ch[x][1]] ^= 1;
rev[x] = false;
swap(ch[x][0], ch[x][1]);
}
}
void build(int l, int r, int f)
{
if(l > r)
return ;
int m = (l + r) >> 1;
ch[m][0] = (m - 1 >= l)? (m - 1 + l) >> 1: 0;
ch[m][1] = (r >= m + 1)? (m + 1 + r) >> 1: 0;
rev[m] = false;
fa[m] = f;
build(l, m - 1, m);
build(m + 1, r, m);
pushup(m);
}
void init()
{
sz[0] = 0;
root = (1 + tot) >> 1;
build(1, tot, 0);
}
inline void rotate(int x, bool f)
{
int y = fa[x];
int z = fa[y];
pushdown(y);
pushdown(x);
ch[y][!f] = ch[x][f];
fa[ch[x][f]] = y;
fa[x] = z;
if(z)
ch[z][ch[z][1] == y] = x;
ch[x][f] = y;
fa[y] = x;
pushup(y);
}
void splay(int x, int g)
{
int y = fa[x];
pushdown(x);
while(y != g)
{
int z = fa[y];
bool f = (ch[y][0] == x);
if(z != g && f == (ch[z][0] == y))
rotate(y, f);
rotate(x, f);
y = fa[x];
}
pushup(x);
if(g == 0)
root = x;
}
void rotateto(int k, int g)
{
int x = root;
pushdown(x);
while(sz[ch[x][0]] != k)
{
if(k < sz[ch[x][0]])
x = ch[x][0];
else
{
k -= sz[ch[x][0]] + 1;
x = ch[x][1];
}
pushdown(x);
}
splay(x, g);
}
void insert(int a, int b)
{
rotateto(a - 1, 0);
rotateto(a, root);
num[++tot] = b;
rev[tot] = false;
ch[tot][0] = ch[tot][1] = 0;
sz[tot] = 1;
KT = tot;
fa[tot] = ch[root][1];
sz[ch[root][1]]++;
sz[root]++;
}
void del(int a)
{
rotateto(a - 1, 0);
rotateto(a + 1, root);
KT = 0;
sz[ch[root][1]]--;
sz[root]--;
}
void reve(int a, int b)
{
rotateto(a - 1, 0);
rotateto(b + 1, root);
rev[KT] ^= 1;
}
int ans[N], anum;
struct NODE
{
int x;
bool f;
};
stack<NODE> S;
void print(int r)
{
while(!S.empty())
S.pop();
NODE u;
u.f = 0;
u.x = r;
S.push(u);
while(!S.empty())
{
u = S.top();
S.pop();
if(u.x)
{
pushdown(u.x);
if(u.f)
{
ans[anum++] = num[u.x];
u.f = 0;
u.x = ch[u.x][1];
S.push(u);
}
else
{
u.f = true;
S.push(u);
u.f = 0;
u.x = ch[u.x][0];
S.push(u);
}
}
}
}
void out()
{
anum = 0;
print(root);
printf("%d", ans[1]);
anum--;
for(int i = 2; i < anum; i++)
printf(" %d", ans[i]);
puts("");
}
int main()
{
//freopen("in.txt", "r", stdin);
int T;
scanf("%d", &T);
while(T--)
{
int n;
scanf("%d", &n);
tot = n + 2;
for(int i = 2; i < tot; i++)
scanf("%d", num + i);
int l, r;
scanf("%d%d", &l, &r);
init();
int m;
scanf("%d", &m);
while(m--)
{
char s[15], op[2];
int a;
scanf("%s", s);
if(s[0] == 'M')
{
scanf("%s", op);
if(s[4] == 'L')
{
if(op[0] == 'L')
l--;
else
r--;
}
else
{
if(op[0] == 'L')
l++;
else
r++;
}
}
else if(s[0] == 'I')
{
scanf("%s%d", op, &a);
r++;
if(op[0] == 'L')
insert(l, a);
else
insert(r, a);
}
else if(s[0] == 'D')
{
scanf("%s", op);
if(op[0] == 'L')
del(l);
else
del(r);
r--;
}
else
reve(l, r);
}
out();
}
return 0;
}
双向链表模拟
用双向链表的话, 就是要处理反转操作, 这里可以这样想, 反转以后其他操作有什么变化, 分析一下会发现, 其实反转和不反转差不多, 只要把插入的位置和删除的位置换一下就好, 所以针对反转操作, 我们就给他以后标记表示是否被反转就好了。代码写的比较冗长, 很多地方都可以放到函数里面减少代码量的。
不多说了, 贴上代码
#include <cstdio>
using namespace std;
#define N 1000007
int nnum;
struct Node
{
int pre, next;
int val;
}node[N];
void scan(int &a)
{
a = 0;
char c = getchar();
bool f = false;
while((c < '0' || c > '9') && c != '-')
c = getchar();
if(c == '-')
{
f = true;
c = getchar();
}
while(c >= '0' && c <= '9')
{
a = (a << 1) + (a << 3) + c - '0';
c = getchar();
}
if(f)
a = -a;
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
int n;
scan(n);
nnum = 1;
node[0].next = -1;
node[0].pre = -1;
int a;
for(int i = 0; i < n; i++)
{
scan(a);
node[nnum].pre = nnum - 1;
node[nnum - 1].next = nnum;
node[nnum].next = -1;
node[nnum].val = a;
nnum++;
}
node[nnum - 1].next = nnum;
node[nnum].pre = nnum - 1;
node[nnum].next = -1;
nnum++;
int ans = 0;
int l, r;
bool f = true;
scan(l);
scan(r);
int m;
scan(m);
while(m--)
{
char s[20];
scanf("%s", s);
if(s[0] == 'R')
{
if(f)
f = false;
else
f = true;
int t = l;
l = r;
r = t;
}
else if(s[0] == 'D')
{
char s2[2];
scanf("%s", s2);
if(s2[0] == 'L')
{
if(f)
{
node[node[l].pre].next = node[l].next;
node[node[l].next].pre = node[l].pre;
l = node[l].next;
}
else
{
node[node[l].pre].next = node[l].next;
node[node[l].next].pre = node[l].pre;
l = node[l].pre;
}
}
else
{
if(!f)
{
node[node[r].pre].next = node[r].next;
node[node[r].next].pre = node[r].pre;
r = node[r].next;
}
else
{
node[node[r].pre].next = node[r].next;
node[node[r].next].pre = node[r].pre;
r = node[r].pre;
}
}
}
else if(s[0] == 'I')
{
char s2[2];
int num;
scanf("%s", s2);
scan(num);
if(s2[0] == 'L')
{
if(f)
{
node[nnum].val = num;
node[nnum].pre = node[l].pre;
node[node[l].pre].next = nnum;
node[l].pre = nnum;
node[nnum].next = l;
l = nnum;
nnum++;
}
else
{
node[nnum].val = num;
node[nnum].next = node[l].next;
node[node[l].next].pre = nnum;
node[l].next = nnum;
node[nnum].pre = l;
l = nnum;
nnum++;
}
}
else
{
if(!f)
{
node[nnum].val = num;
node[nnum].pre = node[r].pre;
node[node[r].pre].next = nnum;
node[r].pre = nnum;
node[nnum].next = r;
r = nnum;
nnum++;
}
else
{
node[nnum].val = num;
node[nnum].next = node[r].next;
node[node[r].next].pre = nnum;
node[r].next = nnum;
node[nnum].pre = r;
r = nnum;
nnum++;
}
}
}
else
{
char s2[2];
scanf("%s", s2);
if(s[4] == 'L')
{
if(s2[0] == 'L')
{
if(f)
{
l = node[l].pre;
}
else
{
int tmp = node[r].pre;
node[node[tmp].pre].next = r;
node[r].pre = node[tmp].pre;
node[node[l].next].pre = tmp;
node[tmp].next = node[l].next;
node[l].next = tmp;
node[tmp].pre = l;
l = tmp;
}
}
else
{
if(f)
{
r = node[r].pre;
}
else
{
int tmp = r;
node[node[r].pre].next = node[tmp].next;
node[node[tmp].next].pre = node[r].pre;
r = node[tmp].next;
node[tmp].next = node[l].next;
node[node[l].next].pre = tmp;
node[tmp].pre = l;
node[l].next = tmp;
}
}
}
else
{
if(s2[0] == 'L')
{
if(f)
l = node[l].next;
else
{
int tmp = l;
node[node[l].next].pre = node[tmp].pre;
node[node[tmp].pre].next = node[l].next;
l = node[tmp].pre;
node[tmp].pre = node[r].pre;
node[node[r].pre].next = tmp;
node[tmp].next = r;
node[r].pre = tmp;
}
}
else
{
if(f)
{
r = node[r].next;
}
else
{
int tmp = node[l].next;
node[node[tmp].next].pre = l;
node[l].next = node[tmp].next;
node[node[r].pre].next = tmp;
node[tmp].pre = node[r].pre;
node[r].pre = tmp;
node[tmp].next = r;
r = tmp;
}
}
}
}
}
ans = 0;
if(!f)
{
node[node[r].pre].next = l;
int tmp = node[l].next;
while(l != r)
{
node[l].next = node[l].pre;
l = node[l].pre;
}
node[l].next = tmp;
}
ans = node[ans].next;
printf("%d", node[ans].val);
ans = node[ans].next;
while(node[ans].next != -1)
{
printf(" %d", node[ans].val);
ans = node[ans].next;
}
puts("");
}
return 0;
}