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; }