codevs 1743 翻转卡片(splay)

来源:互联网 发布:ipad调色软件 编辑:程序博客网 时间:2024/06/06 23:46

题目链接:http://codevs.cn/problem/1743/


这道题作为一个入门题,我是用来练习splay模板的。。。虽然读题读了好久。


#include<cstdio>#include<cstring>#include<iostream>#include<cstdlib>using namespace std;#define maxn (300000+10)int N,root,ans=0;int a[maxn],c[maxn][2],f[maxn],size[maxn],val[maxn];bool rev[maxn];//相当于lazy标记 void update(int x){int l=c[x][0],r=c[x][1];size[x]=size[l]+size[r]+1;}void rotate(int x,int &k){int y=f[x],z=f[y],l,r;if(c[y][0]==x)l=0; else l=1; r=l^1;if(y==k)k=x;else{if(c[z][0]==y)c[z][0]=x;else c[z][1]=x;}f[x]=z; f[y]=x; f[c[x][r]]=y;c[y][l]=c[x][r]; c[x][r]=y;update(y); update(x);}void splay(int x,int &k){while(x!=k){int y=f[x],z=f[y];if(y!=k){if((c[y][0]==x)==(c[z][0]==y))rotate(y,k);else rotate(x,k);}rotate(x,k);}}void push_down(int x){int l=c[x][0],r=c[x][1];rev[x]^=1; rev[l]^=1; rev[r]^=1;swap(c[x][0],c[x][1]);} void built(int L,int R,int F){if(L>R)return ;int mid=(L+R)>>1;if(mid<F)c[F][0]=mid;else c[F][1]=mid;size[mid]=1; val[mid]=a[mid]; f[mid]=F;if(L==R)return ;built(L,mid-1,mid); built(mid+1,R,mid);update(mid);}int find(int k,int rk){//k是当前节点 if(rev[k])push_down(k);int l=c[k][0],r=c[k][1];if(size[l]+1==rk)return k;//找到第一个没有儿子的l else if(size[l]>=rk)return find(l,rk);else return find(r,rk-size[l]-1);}void rever(int L,int R){int x=find(root,L),y=find(root,R+2);splay(x,root),splay(y,c[x][1]);int z=c[y][0];rev[z]^=1;}void input(){scanf("%d",&N);for(int i=1;i<=N;i++)scanf("%d",&a[i+1]);}void solve(){built(1,N+2,0); root=(N+3)>>1; while(val[find(root,2)]!=1){ans++;rever(1,val[find(root,2)]);if(ans>100000){puts("-1");exit(0);}}printf("%d",ans);}int main(){input();solve();return 0;}


0 0