【BZOJ3678】wangxz与OJ
这题不能用rope...因为总的插入点数可能非常大,rope也不回收内存。
Splay加缩点,每次要用到一个点时把点给拆开。
#include <cstdio> #include <algorithm> using namespace std; const int maxn=200010; struct Splay_Tree { struct Node { Node *c[2],*p; int size; int l,r; int w() {return this==p->c[1];} }MEM[maxn],*Null,*root; int IDs; #define ls x->c[0] #define rs x->c[1] Node *NewNode(int l,int r) { if (l>r) return Null; Node *x=&MEM[++IDs]; ls=rs=x->p=Null; x->l=l; x->r=r; x->size=r-l+1; return x; } Splay_Tree() { Null=&MEM[0]; Null->c[0]=Null->c[1]=Null->p=Null; Null->size=0; Null->l=Null->r=0; Node *LeftNode=NewNode(0,0); Node *RightNode=NewNode(0,0); root=LeftNode; root->c[1]=RightNode;RightNode->p=root;root->size=2; } void Update(Node *x) {if (x==Null) return;x->size=ls->size+rs->size+(x->r-x->l+1);} void Rotate(Node *x) { Node *p=x->p; int w=x->w(); if (p==root) root=x; x->p=p->p;p->p->c[p->w()]=x; x->c[!w]->p=p;p->c[w]=x->c[!w]; x->c[!w]=p;p->p=x; Update(p); } void Splay(Node *x,Node *top) { if (x==Null) return; while (x->p!=top) { if (x->p->p==top) {Rotate(x);break;} if (x->w()==x->p->w()) Rotate(x->p),Rotate(x); else Rotate(x),Rotate(x); } Update(x); } Node* Prev(Node *x) {x=ls;while (rs!=Null) x=rs;return x;} Node* Next(Node *x) {x=rs;while (ls!=Null) x=ls;return x;} Node* Select(int k) { Node *x=root; while (k) { int lsz=ls->size,xsz=x->r-x->l+1; if (lsz>=k) x=ls; else if (lsz+xsz<k) k-=lsz+xsz,x=rs; else if (x->r==x->l) return x; else { int l=x->l,r=x->r,mid=l+(k-lsz)-1; Splay(x,Null); Splay(Prev(x),Null); Splay(Next(x),root); Node *Nd=NewNode(mid,mid),*Nl=NewNode(l,mid-1),*Nr=NewNode(mid+1,r); Nd->c[0]=Nl;Nl->p=Nd; Nd->c[1]=Nr;Nr->p=Nd; root->c[1]->c[0]=Nd;Nd->p=root->c[1]; Splay(Nd,Null); return Nd; } } } Node *Build_Tree(int l,int r,int *a) { if (l>r) return Null; int mid=(l+r)>>1; Node *x=NewNode(a[mid],a[mid]); if (l==r) return x; ls=Build_Tree(l,mid-1,a); rs=Build_Tree(mid+1,r,a); ls->p=rs->p=x; Update(x); return x; } void Insert(int pos,int l,int r) { Node *x=NewNode(l,r); Node *ql=Select(pos+1),*qr=Select(pos+2); Splay(ql,Null); Splay(qr,root); root->c[1]->c[0]=x;x->p=root->c[1]; Splay(x,Null); } void Insert(int pos,int *a,int n) { Node *x=Build_Tree(0,n-1,a); Node *ql=Select(pos+1),*qr=Select(pos+2); Splay(ql,Null); Splay(qr,root); root->c[1]->c[0]=x;x->p=root->c[1]; Splay(x,Null); } void Delete(int l,int r) { Node *ql=Select(l),*qr=Select(r+2); Splay(ql,Null); Splay(qr,root); root->c[1]->c[0]=Null; Update(root->c[1]);Update(root); } int At(int x) { Splay(Select(x+1),Null); return root->l; } }T; int s[maxn]; int n,m; int main() { scanf("%d%d",&n,&m); for (int i=0;i<n;i++) scanf("%d",&s[i]); T.Insert(0,s,n); while (m--) { int sym,p,a,b; scanf("%d",&sym); if (sym==0) { scanf("%d%d%d",&p,&a,&b); T.Insert(p,a,b); } else if (sym==1) scanf("%d%d",&a,&b),T.Delete(a,b); else if (sym==2) scanf("%d",&p),printf("%d\n",T.At(p)); } return 0; }