# bzoj3678: wangxz与OJ

splay缩点，把一段连续区间缩成一个结点，访问的时候再把点拆出来

#include <cstdio>
#define MAXN 20003
typedef struct Tree *PTree;
struct Tree
{
int l, r, ct;
PTree left, right, father;
};
PTree root;
int n, Q;
int tmp[MAXN];
void buildtree(PTree &h, int l, int r, PTree fa)
{
h = new Tree;
h->father = fa;
int mid = (l + r) / 2;
h->l = tmp[mid];
h->r = h->l + 1;
h->ct = r - l;
if (l != mid)
buildtree(h->left, l, mid, h);
else
h->left = NULL;
if (mid + 1 != r)
buildtree(h->right, mid + 1, r, h);
else
h->right = NULL;
}
void count(PTree h)
{
h->ct = h->r - h->l;
if (h->left)
h->ct += h->left->ct;
if (h->right)
h->ct += h->right->ct;
}
PTree Lrotate(PTree h)
{
PTree p = h->left;
if (h->father)
{
if (h->father->left == h)
h->father->left = p;
else
h->father->right = p;
}
p->father = h->father;
h->father = p;
if (p->right)
p->right->father = h;
h->left = p->right;
p->right = h;
count(h);
count(p);
if (h == root)
root = p;
return p;
}
PTree Rrotate(PTree h)
{
PTree p = h->right;
if (h->father)
{
if (h->father->left == h)
h->father->left = p;
else
h->father->right = p;
}
p->father = h->father;
h->father = p;
if (p->left)
p->left->father = h;
h->right = p->left;
p->left = h;
count(h);
count(p);
if (h == root)
root = p;
return p;
}
void splay(PTree h)
{
while (h->father)
if (h == h->father->left)
h = Lrotate(h->father);
else
h = Rrotate(h->father);
}
PTree find(PTree h, int p)
{
int lct = h->left ? h->left->ct : 0;
if (p > lct && p <= lct + h->r - h->l)
{
p -= lct;
PTree t;
if (p != 1)
{
t = new Tree;
t->left = h->left;
if (h->left)
h->left->father = t;
t->father = h;
t->right = NULL;
t->l = h->l, t->r = h->l + p - 1;
h->l += p - 1;
h->left = t;
count(t);
p = 1;
}
if (p != h->r - h->l)
{
t = new Tree;
t->right = h->right;
if (h->right)
h->right->father = t;
t->father = h;
t->left = NULL;
t->l = h->l + p, t->r = h->r;
h->r = h->l + p;
h->right = t;
count(t);
}
return h;
}
if (p <= lct)
return find(h->left, p);
else
return find(h->right, p - (lct + h->r - h->l));
}
int main()
{
scanf("%d%d", &n, &Q);
for (int i = 0; i < n; ++i)
scanf("%d", &tmp[i]);
buildtree(root, 0, n, NULL);
while (Q--)
{
int opt;
scanf("%d", &opt);
if (opt == 0)
{
int p, l, r;
PTree t;
scanf("%d%d%d", &p, &l, &r);
++r;
t = new Tree;
t->father = NULL;
t->l = l, t->r = r;
t->ct = r - l + (root ? root->ct : 0);
if (p == 0)
{
t->left = NULL;
t->right = root;
}
else
{
splay(find(root, p));
t->left = root;
t->right = root->right;
if (root->right)
{
root->ct -= root->right->ct;
root->right->father = t;
root->right = NULL;
}
}
if (root)
root->father = t;
root = t;
}
else if (opt == 1)
{
int l, r;
PTree t;
scanf("%d%d", &l, &r);
if (l == 1 && r == root->ct)
root = NULL;
else if (l == 1)
{
splay(find(root, r));
root = root->right;
root->father = NULL;
}
else if (r == root->ct)
{
splay(find(root, l));
root = root->left;
root->father = NULL;
}
else
{
splay(find(root, l));
t = root->left;
t->father = NULL;
root->left = NULL;
root->ct -= t->ct;
splay(find(root, r - l + 1));
root = root->right;
root->father = NULL;
splay(find(root, 1));
root->left = t;
t->father = root;
root->ct += t->ct;
}
}
else
{
int p;
scanf("%d", &p);
printf("%d\n", find(root, p)->l);
}
}
return 0;
}

• 广告
• 抄袭
• 版权
• 政治
• 色情
• 无意义
• 其他

120