poj 3580 SuperMemo
解法:splay显而易见
除了REVOLVE操作,其它的都是splay的常规操作。
REVOLVE操作可以用三次翻转操作来实现。。。如果要实现区间[a,b][b+1,c]的交换,可以依次翻转[a,b],[b+1,c],[a,b]。。。。
p.s.换了下splay的代码风格。。瞬间感觉清新明快不少。。。。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N = (int)1e6+10; 6 const int inf=~0u>>2; 7 int s[N]; 8 struct splaytree{ 9 int cnt,root; 10 int sz[N],ch[N][2],pre[N]; 11 int add[N],rev[N],minn[N],val[N]; 12 inline void newnode(int &t,int v){ 13 t=++cnt; 14 ch[t][0]=ch[t][1]=0; 15 add[t]=rev[t]=0; 16 sz[t]=1; 17 minn[t]=v; 18 val[t]=v; 19 } 20 inline void pushup(int x){ 21 sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1; 22 minn[x]=min(min(minn[ch[x][0]],minn[ch[x][1]]),val[x]); 23 } 24 inline void pushdown(int x){ 25 if(rev[x]){ 26 if(ch[x][0])rev[ch[x][0]]^=1; 27 if(ch[x][1])rev[ch[x][1]]^=1; 28 swap(ch[x][0],ch[x][1]); 29 rev[x]^=1; 30 } 31 if(add[x]){ 32 if(ch[x][0])add[ch[x][0]]+=add[x],minn[ch[x][0]]+=add[x],val[ch[x][0]]+=add[x]; 33 if(ch[x][1])add[ch[x][1]]+=add[x],minn[ch[x][1]]+=add[x],val[ch[x][1]]+=add[x]; 34 add[x]=0; 35 } 36 } 37 inline bool dir(int x){return ch[pre[x]][1]==x;} 38 inline void link(int x,int y,int d){ 39 if(y)ch[y][d]=x; 40 if(x)pre[x]=y; 41 } 42 inline void rotate(int x){ 43 int y=pre[x];bool d=dir(x); 44 pushdown(y);pushdown(x); 45 link(x,pre[y],dir(y)); 46 link(ch[x][!d],y,d); 47 link(y,x,!d); 48 pushup(y); 49 } 50 inline void splay(int x,int goal){ 51 pushdown(x); 52 while(pre[x]!=goal){ 53 if(pre[pre[x]]==goal)rotate(x); 54 else{ 55 if(dir(x)==dir(pre[x]))rotate(pre[x]); 56 else rotate(x); 57 rotate(x); 58 } 59 } 60 pushup(x); 61 if(goal==0)root=x; 62 } 63 inline void select(int k,int goal){ 64 int x=root; 65 pushdown(x); 66 while(sz[ch[x][0]]!=k){ 67 if(sz[ch[x][0]] > k ) x=ch[x][0]; 68 else{ 69 k-=(sz[ch[x][0]]+1);x=ch[x][1]; 70 } 71 pushdown(x); 72 } 73 splay(x,goal); 74 } 75 inline int get(int L,int R){ 76 select(L-1,0); 77 select(R+1,root); 78 return ch[root][1]; 79 } 80 inline void build(int l,int r,int &t,int p){ 81 if(l>r)return; 82 int m=(l+r)>>1; 83 newnode(t,s[m]); 84 build(l,m-1,ch[t][0],t); 85 build(m+1,r,ch[t][1],t); 86 pre[t]=p; 87 pushup(t); 88 } 89 void init(int n){ 90 cnt=root=0; 91 sz[0]=ch[0][0]=ch[0][1]=pre[0]=0; 92 add[0]=rev[0]=0; 93 minn[0]=inf; 94 val[0]=inf; 95 newnode(root,inf); 96 newnode(ch[root][1],inf); 97 pre[cnt]=root; 98 sz[root]=2; 99 build(1,n,ch[ch[root][1]][0],ch[root][1]); 100 pushup(ch[root][1]); 101 pushup(root); 102 } 103 inline void ADD(int L,int R,int d){ 104 int x=get(L,R); 105 add[ch[x][0]]+=d; 106 minn[ch[x][0]]+=d; 107 val[ch[x][0]]+=d; 108 pushup(x); 109 pushup(root); 110 } 111 inline void REVERSE(int L,int R){ 112 int x=get(L,R); 113 rev[ch[x][0]]^=1; 114 } 115 inline void INSERT(int x,int val){ 116 select(x,0); 117 select(x+1,root); 118 newnode(ch[ch[root][1]][0],val); 119 pre[ch[ch[root][1]][0]]=ch[root][1]; 120 pushup(ch[root][1]); 121 pushup(root); 122 } 123 inline void REVOLVE(int L,int R,int t){ 124 int len=(R-L+1);t=(t%len+len)%len; 125 if(t==0)return; 126 REVERSE(L,R-t); 127 REVERSE(R-t+1,R); 128 REVERSE(L,R); 129 } 130 inline void DELETE(int P){ 131 int x=get(P,P); 132 ch[x][0]=0; 133 pushup(x); 134 pushup(root); 135 } 136 inline int MIN(int L,int R){ 137 int x=get(L,R); 138 return minn[ch[x][0]]; 139 } 140 }; 141 splaytree a; 142 int main(){ 143 int n,m,x,y,t; 144 char op[10]; 145 while(~scanf("%d",&n)){ 146 for(int i=1;i<=n;i++)scanf("%d",&s[i]); 147 a.init(n); 148 scanf("%d",&m); 149 while(m--){ 150 scanf("%s",op); 151 if(op[0]=='A'){ 152 scanf("%d%d%d",&x,&y,&t); 153 a.ADD(x,y,t); 154 }else if(op[0]=='R'){ 155 if(op[3]=='E'){ 156 scanf("%d%d",&x,&y); 157 a.REVERSE(x,y); 158 }else{ 159 scanf("%d%d%d",&x,&y,&t); 160 a.REVOLVE(x,y,t); 161 } 162 }else if(op[0]=='I'){ 163 scanf("%d%d",&x,&t); 164 a.INSERT(x,t); 165 }else if(op[0]=='D'){ 166 scanf("%d",&x); 167 a.DELETE(x); 168 }else{ 169 scanf("%d%d",&x,&y); 170 printf("%d\n",a.MIN(x,y)); 171 } 172 } 173 } 174 return 0; 175 }