POJ 3580
題意:配列を与えて、6種類の操作があります.
add x y d:[x,y]のすべての数にdを加算
reverse x y:[x,y]区間反転
revolve x y t:[x,y]サイクル右シフトtビット、tは任意の整数をとることができる
insert x v:x番目の位置にvの値を挿入する数
delete x:x番目の数を削除
min x y:区間[x,y]の最小値を求める
問題解:典型的なsplayは、処理する区間をrootの右の子供の左の木に回転させ、すべての操作をこの上で処理します.
add/reverse:直接タグ処理が可能で、次回の回転時に下伝タグで解決
revolve:右端にt個のノードを含むサブツリーを左端に接ぎ木すると見なす
Insert:挿入する位置をルートノードに移動し、次のノードをルートノードの右の子供に移動することで、この2つのノード間に直接ノードを追加することで解決できます.
delete:xの位置をルートノードに、xの位置をルートノードの右の子供に、左の子供を削除します.
これは私の最初のsplayで、論文を見るのに半日かかって、書くのに半日かかって、デバッグは1日使って、reは無数で、waは1回、繰り返して最適化して、最後にやっと1秒に入りました.回転操作だけでsplayを見ると、確かに水構造ですが、いろいろな反転があって、交代が重なっても卵が痛くなります.
add x y d:[x,y]のすべての数にdを加算
reverse x y:[x,y]区間反転
revolve x y t:[x,y]サイクル右シフトtビット、tは任意の整数をとることができる
insert x v:x番目の位置にvの値を挿入する数
delete x:x番目の数を削除
min x y:区間[x,y]の最小値を求める
問題解:典型的なsplayは、処理する区間をrootの右の子供の左の木に回転させ、すべての操作をこの上で処理します.
add/reverse:直接タグ処理が可能で、次回の回転時に下伝タグで解決
revolve:右端にt個のノードを含むサブツリーを左端に接ぎ木すると見なす
Insert:挿入する位置をルートノードに移動し、次のノードをルートノードの右の子供に移動することで、この2つのノード間に直接ノードを追加することで解決できます.
delete:xの位置をルートノードに、xの位置をルートノードの右の子供に、左の子供を削除します.
これは私の最初のsplayで、論文を見るのに半日かかって、書くのに半日かかって、デバッグは1日使って、reは無数で、waは1回、繰り返して最適化して、最後にやっと1秒に入りました.回転操作だけでsplayを見ると、確かに水構造ですが、いろいろな反転があって、交代が重なっても卵が痛くなります.
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef struct sp_node * Node;
const int MAXN=210010,inf=100000000;
struct sp_node
{
Node pre,ch[2];
int value,lazy,Min,size;// ,lazy , ,
bool rev;//
void init(int _value)
{
pre=ch[0]=ch[1]=NULL;
Min=value=_value;
lazy=0;
size=1;
rev=false;
}
} nstack[MAXN];
int scnt;// splay
Node root;
inline int getsize(Node &x)// x , x=NULL
{
return x?x->size:0;
}
void pushdown(Node &x)// x
{
if(!x)
return;
if(x->lazy)
{
int w=x->lazy;
x->value+=w;
if(x->ch[0])
{
x->ch[0]->lazy+=w;
x->ch[0]->Min+=w;
}
if(x->ch[1])
{
x->ch[1]->lazy+=w;
x->ch[1]->Min+=w;
}
x->lazy=0;
}
if(x->rev)
{
Node t=x->ch[0];
x->ch[0]=x->ch[1];
x->ch[1]=t;
x->rev=false;
if(x->ch[0])
x->ch[0]->rev^=1;
if(x->ch[1])
x->ch[1]->rev^=1;
}
}
void updata(Node &x)// x
{
if(!x)
return;
x->size=1;
x->Min=x->value;
if(x->ch[0])
{
x->Min=min(x->Min,x->ch[0]->Min);
x->size+=x->ch[0]->size;
}
if(x->ch[1])
{
x->Min=min(x->Min,x->ch[1]->Min);
x->size+=x->ch[1]->size;
}
}
void rotate(Node &x, int d) // ,d=0 ,d=1
{
Node y=x->pre;
pushdown(y);
pushdown(x);
pushdown(x->ch[d]);
y->ch[!d]=x->ch[d];
if (x->ch[d]!=NULL) x->ch[d]->pre=y;
x->pre = y->pre;
if (y->pre!=NULL)
{
if (y->pre->ch[0]==y) y->pre->ch[0]=x;
else y->pre->ch[1]=x;
}
x->ch[d]=y,y->pre=x;
updata(y);
if (y == root)// , root
root = x;
}
void splay(Node &x, Node &f) // Splay , x f
{
for (pushdown(x); x!=f;)
{
if(x->pre==f)
{
if(f->ch[0]==x)
rotate(x,1);
else
rotate(x,0);
break;
}
else
{
Node y=x->pre,z=y->pre;
if (z->ch[0] == y)
if (y->ch[0] == x)
rotate(y,1),rotate(x, 1); //
else
rotate(x, 0), rotate(x, 1); //
else if (y->ch[1] == x)
rotate(y, 0), rotate(x, 0); //
else
rotate(x, 1), rotate(x, 0); //
if(z==f)// ,x z , z ,
break;
}
updata(x);
}
updata(x);
}
void select(int k, Node &f)
{
int tmp;
Node t;
for(t=root;;)
{
pushdown(t);
tmp=getsize(t->ch[0]); // t
if (k == tmp + 1) break; // t ,
if (k <= tmp) // k t ,
t = t->ch[0];
else // , , k
k -=tmp+1,t=t->ch[1];
}
pushdown(t);
splay(t, f); //
}
void insert(int pos,int value)
{
select(pos+1,root);
select(pos+2,root->ch[1]);
Node t=nstack+scnt++,x=root->ch[1];
pushdown(root);
pushdown(x);
t->init(value);
t->ch[1]=x;
x->pre=t;
root->ch[1]=t;
t->pre=root;
splay(x,root);
}
void add(int a,int b,int d)
{
select(a,root);
select(b+2,root->ch[1]);
Node x=root->ch[1]->ch[0];
pushdown(x);
updata(x);
x->Min+=d;
x->lazy+=d;
splay(x,root);
}
void reverse(int a,int b)
{
select(a,root);
select(b+2,root->ch[1]);
root->ch[1]->ch[0]->rev^=1;
Node x=root->ch[1]->ch[0];
splay(x,root);
}
void revolve(int a,int b,int t)
{
Node p1,p2;
select(a,root);
select(b+2,root->ch[1]);
select(b+1-t,root->ch[1]->ch[0]);
p1=root->ch[1]->ch[0];
pushdown(p1);
p2=p1->ch[1];
p1->ch[1]=NULL;
select(a+1,root->ch[1]->ch[0]);
p1=root->ch[1]->ch[0];
pushdown(p1);
p1->ch[0]=p2;
p2->pre=p1;
splay(p2,root);
}
int getmin(int a,int b)
{
select(a,root);
select(b+2,root->ch[1]);
Node x=root->ch[1];
pushdown(x);
x=x->ch[0];
pushdown(x);
updata(x);
return x->Min;
}
void erase(int pos)
{
select(pos,root);
select(pos+2,root->ch[1]);
pushdown(root->ch[1]);
root->ch[1]->ch[0]=NULL;
Node x=root->ch[1];
splay(x,root);
}
int main()
{
int i,a,b,c,k,n,m;
scnt=0;
root=nstack+scnt++;
root->init(inf);
root->ch[1]=nstack+scnt++;
root->ch[1]->init(inf);
scanf("%d",&n);
for(i=0; i<n; i++)
{
scanf("%d",&c);
insert(i,c);
}
scanf("%d",&m);
while(m--)
{
char s[50];
scanf("%s", s);
if(s[0]=='A')
{
scanf("%d%d%d",&a,&b,&c);
add(a,b,c);
}
else if(s[0]=='R')
{
scanf("%d%d",&a,&b);
if(s[3]=='E')
reverse(a,b);
else
{
scanf("%d",&k);
int tn=b-a+1;
k=(k%tn+tn)%tn;
if(a==b||k==0)
continue;
revolve(a,b,k);
}
}
else if(s[0]=='I')
{
scanf("%d%d",&a,&c);
insert(a,c);
}
else if(s[0]=='D')
{
scanf("%d",&a);
erase(a);
}
else
{
scanf("%d%d",&a,&b);
int ans=getmin(a,b);
printf("%d
",ans);
}
}
return 0;
}