HDU 3487 Play with Chain

HDU_3487

    拿这个题目练了一下splay的区间的切割,也就是删除、移动、添加一个连续的区间。

#include<stdio.h>
#include<string.h>
#define MAXD 300010
int N, M, T, node, size[MAXD], rev[MAXD], left[MAXD], right[MAXD], pre[MAXD], key[MAXD], ans[MAXD], P;
void newnode(int &cur, int k)
{
cur = ++ node;
key[cur] = k;
size[cur] = 1;
rev[cur] = 0;
left[cur] = right[cur] = 0;
}
void update(int cur)
{
size[cur] = size[left[cur]] + size[right[cur]] + 1;
}
void pushdown(int cur)
{
if(rev[cur])
{
int ls = left[cur], rs = right[cur];
rev[ls] = (rev[ls] + 1) & 1, rev[rs] = (rev[rs] + 1) & 1;
left[cur] = rs, right[cur] = ls;
rev[cur] = 0;
}
}
void build(int &cur, int x, int y, int p)
{
int mid = (x + y) / 2;
newnode(cur, mid);
pre[cur] = p;
if(x == y)
return ;
if(x < mid)
build(left[cur], x, mid - 1, cur);
if(mid < y)
build(right[cur], mid + 1, y, cur);
update(cur);
}
void init()
{
T = node = size[0] = left[0] = right[0] = 0;
newnode(T, 0), newnode(right[T], N + 1);
size[T] = 2, pre[T] = 0, pre[right[T]] = T;
build(left[right[T]], 1, N, right[T]);
update(right[T]), update(T);
}
void leftrotate(int x)
{
int y = right[x], p = pre[x];
right[x] = left[y];
if(right[x])
pre[right[x]] = x;
left[y] = x;
pre[x] = y;
pre[y] = p;
if(p == 0)
T = y;
else
right[p] == x ? right[p] = y : left[p] = y;
update(x);
}
void rightrotate(int x)
{
int y = left[x], p = pre[x];
left[x] = right[y];
if(left[x])
pre[left[x]] = x;
right[y] = x;
pre[x] = y;
pre[y] = p;
if(p == 0)
T = y;
else
right[p] == x ? right[p] = y : left[p] = y;
update(x);
}
void splay(int x, int goal)
{
int y, z;
for(;;)
{
if((y = pre[x]) == goal)
break;
if((z = pre[y]) == goal)
right[y] == x ? leftrotate(y) : rightrotate(y);
else
{
if(right[z] == y)
{
if(right[y] == x)
leftrotate(z), leftrotate(y);
else
rightrotate(y), leftrotate(z);
}
else
{
if(left[y] == x)
rightrotate(z), rightrotate(y);
else
leftrotate(y), rightrotate(z);
}
}
}
update(x);
}
void rotateto(int k, int goal)
{
int i = T;
for(;;)
{
pushdown(i);
if(k == size[left[i]] + 1)
break;
if(k <= size[left[i]])
i = left[i];
else
k -= size[left[i]] + 1, i = right[i];
}
splay(i, goal);
}
void cut(int x, int y, int z)
{
int k, t;
rotateto(x, 0), rotateto(y + 2, T);
t = left[right[T]];
left[right[T]] = 0;
update(right[T]), update(T);
rotateto(z + 1, 0), rotateto(z + 2, T);
pre[t] = right[T];
left[right[T]] = t;
update(right[T]), update(T);
}
void flip(int x, int y)
{
int k;
rotateto(x, 0), rotateto(y + 2, T);
k = left[right[T]];
rev[k] = (rev[k] + 1) & 1;
}
void solve()
{
int i, x, y, z;
char b[10];
for(i = 0; i < M; i ++)
{
scanf("%s", b);
if(b[0] == 'C')
{
scanf("%d%d%d", &x, &y, &z);
cut(x, y, z);
}
else
{
scanf("%d%d", &x, &y);
flip(x, y);
}
}
}
void dfs(int cur)
{
pushdown(cur);
if(left[cur])
dfs(left[cur]);
ans[P ++] = key[cur];
if(right[cur])
dfs(right[cur]);
}
void printresult()
{
int i;
P = 0;
dfs(T);
printf("%d", ans[1]);
for(i = 2; i < P - 1; i ++)
printf(" %d", ans[i]);
printf("\n");
}
int main()
{
while(scanf("%d%d", &N, &M) == 2)
{
if(N < 0 && M < 0)
break;
init();
solve();
printresult();
}
return 0;
}


原文地址:https://www.cnblogs.com/staginner/p/2429202.html