从搞acm以来,一直负责队内的图论,搜索,树形DP。今年的regional结束了,想学学数据结构了
splay用的是孟神的模板,发现splay就是一个splay操作,没什么困难的,果断搞起
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
#define mid (L+R>>1)
const int M = (int)1e6+10;
const int inf=~0u>>2;
int s[M],n,m;
struct splaytree{
int cnt,root;
int sz[M],ch[M][2],pre[M];
int add[M],rev[M],minn[M],val[M];
inline bool dir(int x){
return ch[pre[x]][1]==x;
}
inline void link(int x,int y,int d){
if(y)ch[y][d]=x;
if(x)pre[x]=y;
}
inline void rotate(int x){
int y=pre[x],d=dir(x);
pushdown(y);pushdown(x);
link(x,pre[y],dir(y));
link(ch[x][!d],y,d);
link(y,x,!d);
pushup(y);
}
inline void splay(int x,int goal){
pushdown(x);
while(pre[x]!=goal){
if(pre[pre[x]]==goal){
rotate(x);
} else{
if(dir(x)==dir(pre[x])){
rotate(pre[x]);
} else{
rotate(x);
}
rotate(x);
}
}
pushup(x);
if(goal==0)root=x;
}
void newnode(int &t,int v){
t=++cnt;
ch[t][0]=ch[t][1]=0;
sz[t]=1;
add[t]=rev[t]=0;
val[t]=minn[t]=v;
}
void pushup(int t){
sz[t]=sz[ch[t][0]]+sz[ch[t][1]]+1;
minn[t]=min(val[t],min(minn[ch[t][0]],minn[ch[t][1]]));
}
void pushdown(int t){
if(ch[t][0]){
add[ch[t][0]]+=add[t];
val[ch[t][0]]+=add[t];
minn[ch[t][0]]+=add[t];
rev[ch[t][0]]^=rev[t];
}
if(ch[t][1]){
add[ch[t][1]]+=add[t];
val[ch[t][1]]+=add[t];
minn[ch[t][1]]+=add[t];
rev[ch[t][1]]^=rev[t];
}
if(rev[t])swap(ch[t][0],ch[t][1]);
rev[t]=add[t]=0;
}
void build(int L,int R,int &t,int p){
if(R<L)return ;
newnode(t,s[mid]);
build(L,mid-1,ch[t][0],t);
build(mid+1,R,ch[t][1],t);
pre[t]=p;pushup(t);
}
void init(int n){
cnt=root=0;
sz[0]=pre[0]=0;
ch[0][0]=ch[0][1]=0;
add[0]=rev[0]=0;
minn[0]=val[0]=inf;
newnode(root,inf);
newnode(ch[root][1],inf);
pre[cnt]=root,sz[root]=2;
build(1,n,ch[ch[root][1]][0],ch[root][1]);
pushup(ch[root][1]);pushup(root);
}
int select(int t,int k){
pushdown(t);
if(sz[ch[t][0]]==k)return t;
if(sz[ch[t][0]]>k){
return select(ch[t][0],k);
}else{
return select(ch[t][1],k-sz[ch[t][0]]-1);
}
}
void get(int l,int r){
splay(select(root,l-1),0);
splay(select(root,r+1),root);
}
void Add(int l,int r,int d){
get(l,r);
int x=ch[ch[root][1]][0];
add[x]+=d;
minn[x]+=d;
val[x]+=d;
pushup(ch[root][1]);
pushup(root);
}
void reverse(int l,int r){
get(l,r);
int x=ch[ch[root][1]][0];
rev[x]^=1;
}
int Min(int l,int r){
get(l,r);
int x=ch[ch[root][1]][0];
return minn[x];
}
void del(int x){
get(x,x);
ch[ch[root][1]][0]=0;
pushup(ch[root][1]);
pushup(root);
}
void insert(int x,int y){
get(x+1,x);
newnode(ch[ch[root][1]][0],y);
pre[ch[ch[root][1]][0]]=ch[root][1];
pushup(ch[root][1]);
pushup(root);
}
void revolve(int L,int R,int t){
int len=(R-L+1);
t=(t%len+len)%len;
if(t==0)return;
reverse(L,R-t);
reverse(R-t+1,R);
reverse(L,R);
}
}tree;
int main(){
while(cin>>n){
for(int i=1;i<=n;i++){
scanf("%d",&s[i]);
}
tree.init(n);
cin>>m;
while(m--){
char op[15];
scanf("%s",op);
if(op[0]=='A'){
int x,y,d;
scanf("%d%d%d",&x,&y,&d);
tree.Add(x,y,d);
} else if(op[0]=='R'&&op[3]=='E'){
int x,y;
scanf("%d%d",&x,&y);
tree.reverse(x,y);
} else if(op[0]=='R'&&op[3]=='O'){
int x,y,t;
scanf("%d%d%d",&x,&y,&t);
tree.revolve(x,y,t);
} else if(op[0]=='I'){
int x,y;
scanf("%d%d",&x,&y);
tree.insert(x,y);
} else if(op[0]=='D'){
int x;
scanf("%d",&x);
tree.del(x);
} else if(op[0]=='M'){
int x,y;
scanf("%d%d",&x,&y);
printf("%d\n",tree.Min(x,y));
}
}
}
return 0;
}
这个代码有186行之长。。。,可是发现核心的就是下面这点
inline bool dir(int x){
return ch[pre[x]][1]==x;
}
inline void link(int x,int y,int d){
if(y)ch[y][d]=x;
if(x)pre[x]=y;
}
inline void rotate(int x){
int y=pre[x],d=dir(x);
pushdown(y);pushdown(x);
link(x,pre[y],dir(y));
link(ch[x][!d],y,d);
link(y,x,!d);
pushup(y);
}
inline void splay(int x,int goal){
pushdown(x);
while(pre[x]!=goal){
if(pre[pre[x]]==goal){
rotate(x);
} else{
if(dir(x)==dir(pre[x])){
rotate(pre[x]);
} else{
rotate(x);
}
rotate(x);
}
}
pushup(x);
if(goal==0)root=x;
}
就是个splay操作,完成一系列的翻转等等。。。