BZOJ 1269 文本编辑器Editor
解析:BZOJ1507加强版,首先是数据加强,然后是多了一个reverse,似乎没什么,但是这意味着你需要加上一系列的pushdown······千万不要把pushdown位置搞错,千万不要多打,千万不要少打,不要作死。
Source:
#include
#include
#include
#include
#include
#include
#include
using namespace std;
inline void R(int &v)
{
char c = 0;
bool p = true;
v = 0;
while(!isdigit(c))
{
if(c == '-')
p = false;
c = getchar();
}
while(isdigit(c))
{
v = (v << 3) + (v << 1) + (c ^ '0');
c = getchar();
}
if(!p)
v = -v;
}
template
struct memorypool {
T buf[size], *tail, *end, *st[size];
int top;
memorypool() : top(0), tail(buf), end(buf + size) {}
inline T *alloc() {
if (top) return st[--top];
if (tail != end) return tail++;
return new T;
}
inline void recycle(T *p) {
if (top > size) delete p;
else st[top++] = p;
}
};
const int MAXN = 1024 * 1024 * 4 ;
const int MAX = 1024 * 1024 * 4 ;
template
struct Splay
{
enum Relation { L = 0, R = 1 };
struct node
{
node *child[2], *parent, **root;
int size;
T value;
bool reverse, bound;
inline void init(node *parent, node **root, const T &value, bool bound = false)
{
this->parent = parent, this->root = root, this->value = value, this->bound = bound;
this->reverse = false, this->size = 1, child[L] = child[R] = NULL;
}
inline void recycle(memorypool &pool)
{
if(child[L]) pool.recycle(child[L]);
if(child[R]) pool.recycle(child[R]);
}
inline void pushdown()
{
if(reverse)
{
if(child[L]) child[L]->reverse ^= 1;
if(child[R]) child[R]->reverse ^= 1;
swap(child[L], child[R]), reverse = false;
}
}
inline Relation relation() { return this == parent->child[L] ? L : R; }
inline void maintain() { pushdown(), size = (child[L] ? child[L]->size : 0) + (child[R] ? child[R]->size : 0) + 1; }
inline void rotate()
{
if(parent->parent) parent->parent->pushdown();
parent->pushdown(), pushdown();
Relation x = relation();
node *oldparent = parent;
if(oldparent->parent) oldparent->parent->child[oldparent->relation()] = this;
parent = oldparent->parent, oldparent->child[x] = child[x ^ 1];
if(child[x ^ 1]) child[x ^ 1]->parent = oldparent;
child[x ^ 1] = oldparent, oldparent->parent = this, oldparent->maintain(), maintain();
if(!parent) *root = this;
}
inline void splay(node *targetparent = NULL)
{
while(parent != targetparent)
{
if(parent->parent == targetparent) rotate();
else
{
parent->parent->pushdown(), parent->pushdown();
if(parent->relation() == relation()) parent->rotate(), rotate();
else rotate(), rotate();
}
}
}
inline int rank() { return child[L] ? child[L]->size : 0; }
inline int pos() { return splay(), child[L] ? child[L]->size : 0; }
} *root;
memorypool pool;
Splay() : root(NULL) { buildbound(L), buildbound(R); }
inline node *buildrange(const T *a, int l, int r, node *parent)
{
if(l > r) return NULL;
register int mid = l + r >> 1;
node *v = pool.alloc();
v->init(parent, &root, a[mid - 1]);
if(l != r) v->child[L] = buildrange(a, l, mid - 1, v), v->child[R] = buildrange(a, mid+1, r, v);
return v->maintain(), v;
}
inline void buildbound(Relation x)
{
node **v = &root, *parent = NULL;
while(*v) parent = (*v), parent->size++, v = &parent->child[x];
(*v) = pool.alloc(), (*v)->init(parent, &root, 0, true), (*v)->maintain();
}
inline node *select(int k)
{
k++;
node *v = root;
while(v->pushdown(), v->rank() + 1 != k) v = (v->rank() >= k ? v->child[L] : (k -= v->rank() + 1, v->child[R]));
return v->splay(), v;
}
inline node *&select(int l, int r)
{
node *vl = select(l - 1), *vr = select(r + 1);
return vl->splay(), vr->splay(vl), vr->child[L];
}
inline void erase(int l, int r)
{
node *&range = select(l, r);
range->recycle(pool), pool.recycle(range), range = NULL;
root->child[R]->maintain(), root->maintain();
}
inline void insert(int pos, const T *a, int n)
{
node *&range = select(pos + 1, pos);
range = buildrange(a, 1, n, root->child[R]);
root->child[R]->maintain(), root->maintain();
}
inline void reverse(int l, int r)
{
node *range = select(l ,r);
range->reverse ^= 1;
}
inline int size() { return root->size - 2; }
};
Splay splay;
int main()
{
static char type[10], a[MAX], c;
static int x, pos, n;
R(n);
while(n--)
{
scanf("%s", type);
if(type[0] == 'I')
{
R(x);
int cnt = 0;
while(true)
{
c = getchar();
if(c >= 32 && c <= 126)
a[cnt++] = c;
if(cnt == x) break;
}
splay.insert(pos, a, x);
}
else if(type[0] == 'M') R(x), pos = x;
else if(type[0] == 'D') R(x), splay.erase(pos + 1, pos + x);
else if(type[0] == 'R') R(x), splay.reverse(pos + 1, pos + x);
else if(type[0] == 'G') cout << splay.select(pos + 1)->value << '\n';
else if(type[0] == 'P') pos--;
else if(type[0] == 'N') pos++;
}
return 0;
}