【*】POJ-3580(ストレッチツリー-slpay tree)
ツリーを伸ばすメリット:
Splay Treeは絶えず調整されるだけで、追加のタグは導入されていないため、ツリー構造は標準BSTと何の違いもなく、空間的な観点からTreap、Red-Black Tree、AVLよりもずっと効率的である.構造は変わらないので、左回転と右回転による操作であればSplay Treeの性質に影響を及ぼさないため、BSTの中でも最も豊富な機能を提供している.迅速な分割とマージ(ここでは、元のツリーを2本のツリーに分割することを意味し、1本のツリーのすべてのノードが他のツリーよりも小さく、逆のプロセスを指す)を含み、実現が極めて便利である.これは他の構造では実現しにくい.その時間効率もかなり安定しており、Treapとほぼ同等である.
Splay Treeは絶えず調整されるだけで、追加のタグは導入されていないため、ツリー構造は標準BSTと何の違いもなく、空間的な観点からTreap、Red-Black Tree、AVLよりもずっと効率的である.構造は変わらないので、左回転と右回転による操作であればSplay Treeの性質に影響を及ぼさないため、BSTの中でも最も豊富な機能を提供している.迅速な分割とマージ(ここでは、元のツリーを2本のツリーに分割することを意味し、1本のツリーのすべてのノードが他のツリーよりも小さく、逆のプロセスを指す)を含み、実現が極めて便利である.これは他の構造では実現しにくい.その時間効率もかなり安定しており、Treapとほぼ同等である.
/*==========================================================*\
| (splay tree)
| :
| (1) value
| (2)
| (3) k ( )
| (4)
| (5)
| (6)
\*==========================================================*/
#define type int
#define MAXN 2000005
#define MAXL 100005
#define INF (1<<30)
struct Splay_Tree
{
struct Node//
{
Node *c[2],*p;
int value,size,Min,lazy;
bool rev;
}*root,*null,*lb,*rb,S[MAXN];
int scnt;
//inline int max(int a,int b) {return a>b?a:b;}
inline Node * NewNode(int value,Node *p)//
{
Node *e=S+(++scnt);
e->value=value;
e->size=1;
e->p=p;
e->Min=value;
e->lazy=0;
e->rev=false;
e->c[0]=e->c[1]=null;
return e;
}
inline void Update(Node *p)//
{
if (p==null) return;
p->size=p->c[0]->size+p->c[1]->size+1;
p->Min=MY_MIN(p->value,MY_MIN(p->c[0]->Min,p->c[1]->Min));
}
inline void PushDown(Node *x)//
{
if(x==null) return;
if(x->rev)
{
x->rev=false;
Node *t=x->c[0]; x->c[0]=x->c[1]; x->c[1]=t;
x->c[0]->rev=!x->c[0]->rev;
x->c[1]->rev=!x->c[1]->rev;
//int w=x->ll; x->ll=x->rr; x->rr=w;
}
if(x->lazy)
{
int w=x->lazy;
x->value+=w;
x->Min+=w;
x->c[0]->lazy+=w;
x->c[1]->lazy+=w;
x->lazy=0;
}
}
inline void Rotate(Node *x,int k)// k=0; k=1;
{
Node *y=x->p;
PushDown(x->c[0]);
PushDown(x->c[1]);
PushDown(y->c[!k]);
y->c[k]=x->c[!k];
y->c[k]->p=y;
x->p=y->p;
if(y->p->c[0]==y)
y->p->c[0]=x;
else
y->p->c[1]=x;
y->p=x;
x->c[!k]=y;
Update(y);
Update(x);
if(root==y) root=x;
}
inline void Splay(Node *x,Node *y)//
{
PushDown(x);
while(x->p!=y)
{
if(x->p->p==y)
{
if(x->p->c[0]==x)
Rotate(x,0);
else
Rotate(x,1);
}
else if(x->p->p->c[0]==x->p)
{
if(x->p->c[0]==x)
Rotate(x->p,0),Rotate(x,0);
else
Rotate(x,1),Rotate(x,0);
}
else
{
if(x->p->c[1]==x)
Rotate(x->p,1),Rotate(x,1);
else
Rotate(x,0),Rotate(x,1);
}
}
Update(x);
}
inline void Select(int k,Node *y)
{
Node *x=root;
PushDown(x);
while(k!=x->c[0]->size+1)
{
if(k<=x->c[0]->size)
x=x->c[0];
else
{
k-=x->c[0]->size+1;
x=x->c[1];
}
PushDown(x);
}
Splay(x,y);
}
inline void MakeTree(int l,int r,type C[],Node *p,int side)
{
if(l>r) return;
int mid=(l+r)>>1;
Node *x;
x=NewNode(C[mid],p);
p->c[side]=x;
MakeTree(l,mid-1,C,x,0);
MakeTree(mid+1,r,C,x,1);
Update(x);
}
inline void Insert(int pos,int cnt,type C[])// pos cnt
{
Select(pos+1,null);
Select(pos+2,root);
MakeTree(1,cnt,C,root->c[1],0);
Splay(root->c[1]->c[0],null);
}
inline void Add(int pos,int cnt,type value)// pos cnt value
{
Select(pos,null);
Select(pos+cnt+1,root);
root->c[1]->c[0]->lazy+=value;
Splay(root->c[1]->c[0],null);
}
inline void Delete(int pos,int cnt)// pos cnt
{
Select(pos,null);
Select(pos+cnt+1,root);
root->c[1]->c[0]=null;
Splay(root->c[1],null);
}
inline void Reverse(int pos,int cnt)// pos cnt
{
Select(pos,null);
Select(pos+cnt+1,root);
root->c[1]->c[0]->rev=!root->c[1]->c[0]->rev;
Splay(root->c[1]->c[0],null);
}
inline void Revolve(int a,int b,int k)// [a,b] k
{
int len=(b-a+1),A,B,C;
k=((k%len)+len)%len;
if(k==0) return;
A=a;B=b-k;C=b; // [A,B],[B+1,C];
Node *p1,*p2,*p3,*p4;
Select(A,null); p1=root; //A-1;
Select(C+2,null); p2=root; //C+1;
Select(A+1,null); p3=root; //A;
Select(B+1,null); p4=root; //B;
Select(A,null); // A-1 root
Select(C+2,p1); // C+1 A-1
Select(B+1,p2); // B C+1
Node *x,*y;
x=p4->c[1]; // b , a
p4->c[1]=null;
p3->c[0]=x;
Splay(p3,null); // a root,
}
inline type GetMin(int pos,int cnt)// pos cnt
{
Select(pos,null);
Select(pos+cnt+1,root);
PushDown(root->c[1]->c[0]);
return root->c[1]->c[0]->Min;
}
void Index(int pos)
{
Select(pos+1,null);
printf("*%d
",root->value);
}
inline void Print()//
{
int i;
for(i=1;i<scnt-1;i++)
Index(i);
}
inline void Init()
{
scnt=-1;
null=0;
null=NewNode(INF,0);
null->size=0;
lb=root=NewNode(INF,null);
rb=root->c[1]=NewNode(INF,root);
Update(root);
}
}Splay;
int N,M,pos;
type C[MAXL],ans;
char s[20];
int main()
{
int i,j,a,b,c,k;
Splay.Init();
scanf("%d",&N);
for(i=1;i<=N;i++)
scanf("%d",&C[i]);
//printf("*
");
//Stop;
Splay.Insert(0,N,C);
//Splay.Print();
scanf("%d",&M);
while(M--)
{
scanf("%s",s);
if(s[0]=='A')
{
scanf("%d%d%d",&a,&b,&c);
Splay.Add(a,b-a+1,c);
}
else if(s[0]=='R')
{
scanf("%d%d",&a,&b);
if(s[3]=='E')
Splay.Reverse(a,b-a+1);
else
{
scanf("%d",&k);
Splay.Revolve(a,b,k);
//Splay.Print();
}
}
else if(s[0]=='I')
{
scanf("%d%d",&a,&C[1]);
Splay.Insert(a,1,C);
}
else if(s[0]=='D')
{
scanf("%d",&a);
Splay.Delete(a,1);
}
else
{
scanf("%d%d",&a,&b);
ans=Splay.GetMin(a,b-a+1);
printf("%d
",ans);
}
}
return 0;
}