http://poj.org/problem?id=3580
注意,inf设的不要太小,还有对于题目输入数据的各种处理(可能有非法数据),要注意判断,具体见代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int inf = ~0u>>2;
#define L ch[x][0]
#define R ch[x][1]
#define KT (ch[ ch[rt][1] ][0])
const int maxn = 200010;
struct SplayTree {
int sz[maxn];
int ch[maxn][2];
int pre[maxn];
int rt,top;
inline int min(int a,int b) {return a<b?a:b;}
inline void down(int x){
if(!x) return ;
if(flip[x]) {
flip[ L ] ^= 1;
flip[ R ] ^= 1;
swap(L,R);
flip[x]=0;
}
if(add[x]) {
if(L) {
mi[L] += add[x];
add[L] += add[x];
val[L] += add[x];
}
if(R){
mi[R] += add[x];
add[R] += add[x];
val[R] += add[x];
}
add[x]=0;
}
}
inline void up(int x){
mi[x]=min(val[x],min(mi[ L ],mi[ R ]));
sz[x]= 1 + sz[ L ] + sz[ R ];
}
inline void Rotate(int x,int f){
int y=pre[x];
down(y);
down(x);
ch[y][!f] = ch[x][f];
pre[ ch[x][f] ] = y;
pre[x] = pre[y];
if(pre[x]) ch[ pre[y] ][ ch[pre[y]][1] == y ] =x;
ch[x][f] = y;
pre[y] = x;
up(y);
}
inline void Splay(int x,int goal){//将x旋转到goal的下面
down(x);//防止pre[x]就是目标点,下面的循环就进不去了,x的信息就传不下去了
while(pre[x] != goal){
down(pre[pre[x]]); down(pre[x]);down(x);//在旋转之前需要先下传标记,因为节点的位置可能会发生改变
if(pre[pre[x]] == goal) Rotate(x , ch[pre[x]][0] == x);
else {
int y=pre[x],z=pre[y];
int f = (ch[z][0]==y);
if(ch[y][f] == x) Rotate(x,!f),Rotate(x,f);
else Rotate(y,f),Rotate(x,f);
}
}
up(x);
if(goal==0) rt=x;
}
inline void RTO(int k,int goal){//将第k位数旋转到goal的下面
int x=rt;
down(x);
while(sz[ L ]+1 != k) {
if(k < sz[ L ] + 1 ) x=L;
else {
k-=(sz[ L ]+1);
x = R;
}
down(x);
}
Splay(x,goal);
}
void vist(int x){
if(x){
printf("结点%2d : 左儿子 %2d 右儿子 %2d %2d mi:%d sum:%2d add:%2d\n",x,L,R,val[x],mi[x],sum[x],add[x]);
vist(L);
vist(R);
}
}
void debug(){ vist(rt);}
void Newnode(int &x,int c,int f){
x=++top;
L = R = 0; sz[x]=1; pre[x]=f;
mi[x]=val[x]=c; flip[x]=add[x]=0;
}
inline void build(int &x,int l,int r,int f){
if(l>r) return ;
int m=l+r>>1;
Newnode(x,num[m],f);
build(L , l , m-1 , x);
build(R , m+1 , r , x);
pre[x]=f;
up(x);
}
inline void init(int n){
ch[0][0]=ch[0][1]=pre[0]=sz[0]=0;
rt=top=0;
flip[0]=val[0]=add[0]=0; mi[0]=inf;
Newnode(rt,inf,0);
Newnode(ch[rt][1],inf,rt);
sz[rt]=2;
for(int i=1;i<=n;i++) scanf("%d",&num[i]);
build(KT,1,n,ch[rt][1]);
up(ch[rt][1]); up(rt);
}
void MIN() {
int x,y;
scanf("%d%d",&x,&y);
if(x>y) swap(x,y);
RTO(x,0);
RTO(y+2,rt);
printf("%d\n",mi[KT]);
}
void ADD() {
int x,y,d;
scanf("%d%d%d",&x,&y,&d);
if(x>y) swap(x,y);
RTO(x,0);
RTO(y+2,rt);
add[KT] += d;
val[KT] += d;
mi[KT] += d;
}
void REVERSE(){
int x,y;
scanf("%d%d",&x,&y);
if(x>y) swap(x,y);
RTO(x,0);
RTO(y+2,rt);
flip[KT] ^= 1;
}
void INSERT() {
int x,p;
scanf("%d%d",&x,&p);
RTO(x+1,0);
RTO(x+2,rt);
Newnode(KT,p,ch[rt][1]);
up(ch[rt][1]);up(rt);
}
void DELETE() {
int x;
scanf("%d",&x);
RTO(x,0);
RTO(x+2,rt);
KT = 0;
up(ch[rt][1]); up(rt);
}
void REVOLVE() {
int x,y,t,l,r;
scanf("%d%d%d",&x,&y,&t);
if(x>y) swap(x,y);
t%=(y-x+1);
t=(t+y-x+1) % (y-x+1);
if(t==0) return ;
l=y-t+1,r=y;
RTO(l,0);
RTO(r+2,rt);
int tmp=KT;
KT=0;
up(ch[rt][1]);up(rt);
RTO(x,0);
RTO(x+1,rt);
KT=tmp; pre[tmp] = ch[rt][1];
up(ch[rt][1]);up(rt);
}
int mi[maxn];
int num[maxn];
int add[maxn];
int sum[maxn];
int flag;
int flip[maxn];
int val[maxn];
}spt;
int main() {
int n,m;
scanf("%d",&n);
spt.init(n);
char op[10];
scanf("%d",&m);
while(m--) {
scanf("%s",op);
if(op[0]=='A') {
spt.ADD();
} else if(op[0]=='M') {
spt.MIN();
} else if(op[0]=='I') {
spt.INSERT();
} else if(op[0]=='D') {
spt.DELETE();
} else if(strcmp(op,"REVERSE") == 0) {
spt.REVERSE();
} else if(strcmp(op,"debug") == 0){
spt.debug();
} else {
spt.REVOLVE();
}
}
return 0;
}