Splay
离散化+Splay维护序列……
好吧主要说一下我做这道题遇到的几个错误点:
1.离散化
2.由于找到的这个数的位置一定是大于等于 i 的,所以其实在把它splay到根以后,i 结点只能splay到它的左儿子,而不是右儿子……而且相应的,代表这个区间的应该是c[c[root][0]][1]呃……就是root的左儿子的右儿子= =整个反了一下……好吧不要在意这些细节,我也不知道为什么我突然要反过来写[捂脸熊]
3.进行了修改操作以后一定要立即splay修改的结点!在这题中就是当找到最小结点,将其置为无穷大后,一定要splay一下……否则就WA了TAT
1 /************************************************************** 2 Problem: 1552 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:2764 ms 7 Memory:4888 kb 8 ****************************************************************/ 9 10 //BZOJ 1552 11 #include<cstdio> 12 #include<cstring> 13 #include<cstdlib> 14 #include<iostream> 15 #include<algorithm> 16 #define rep(i,n) for(int i=0;i<n;++i) 17 #define F(i,j,n) for(int i=j;i<=n;++i) 18 #define D(i,j,n) for(int i=j;i>=n;i--) 19 using namespace std; 20 typedef long long LL; 21 inline int getint(){ 22 int r=1,v=0; char ch=getchar(); 23 for(;!isdigit(ch);ch=getchar()) if (ch==‘-‘) r=-1; 24 for(; isdigit(ch);ch=getchar()) v=v*10+ch-‘0‘; 25 return r*v; 26 } 27 const int N=1e5+10,INF=~0u>>2; 28 /******************template*********************/ 29 struct node{int v,pos;}a[N]; 30 bool operator < (node a,node b){return a.pos<b.pos;} 31 bool cmp(node a,node b){return a.v<b.v||(a.v==b.v && a.pos<b.pos);} 32 int c[N][2],fa[N],v[N],mn[N],size[N],tot,root,n; 33 bool rev[N]; 34 #define L c[x][0] 35 #define R c[x][1] 36 void Push_down(int x){ 37 if (rev[x]){ 38 rev[L]^=1; rev[R]^=1; 39 swap(L,R); rev[x]=0; 40 } 41 } 42 void Push_up(int x){ 43 mn[x]=v[x]; 44 if (L) mn[x]=min(mn[x],mn[L]); 45 if (R) mn[x]=min(mn[x],mn[R]); 46 size[x]=size[L]+size[R]+1; 47 } 48 void Rotate(int x){ 49 int y=fa[x],z=fa[y],l=c[y][1]==x,r=l^1; 50 c[z][c[z][1]==y]=x; 51 fa[x]=z; fa[y]=x; fa[c[x][r]]=y; 52 c[y][l]=c[x][r]; c[x][r]=y; 53 Push_up(y); 54 } 55 int st[N]; 56 void Preview(int x){ 57 int top=0; st[++top]=x; 58 for(int i=x;fa[i];i=fa[i]) 59 st[++top]=fa[i]; 60 D(i,top,1) Push_down(st[i]); 61 } 62 void splay(int x,int s=0){ 63 int y; 64 for(Preview(x);fa[x]!=s;Rotate(x)) 65 if (fa[y=fa[x]]!=s) Rotate(c[y][1]==x^c[fa[y]][1]==y?x:y); 66 Push_up(x); 67 if (!s) root=x; 68 } 69 void New_node(int &x,int f,int key){ 70 x=++tot; 71 fa[x]=f; 72 v[x]=mn[x]=key; 73 rev[x]=L=R=0; 74 size[x]=1; 75 } 76 void Build(int &x,int f,int l,int r){ 77 if (l>r) return; 78 int mid=l+r>>1; 79 New_node(x,f,a[mid].v); 80 Build(L,x,l,mid-1); 81 Build(R,x,mid+1,r); 82 Push_up(x); 83 } 84 int kth(int x,int k){ 85 Push_down(x); 86 if (size[L]+1==k) return x; 87 else if (size[L]>=k) return kth(L,k); 88 else return kth(R,k-size[L]-1); 89 } 90 int findmin(int x){ 91 Push_down(x); 92 if (L && mn[x]==mn[L]) return findmin(L); 93 else if (R && mn[x]==mn[R]) return findmin(R)+size[L]+1; 94 else {v[x]=INF;Push_up(x); return size[L]+1;} 95 } 96 int main(){ 97 n=getint(); 98 v[0]=mn[0]=a[0].v=a[n+1].v=INF; 99 F(i,1,n) {a[i].v=getint();a[i].pos=i;} 100 sort(a+1,a+n+1,cmp); 101 F(i,1,n) a[i].v=i; 102 sort(a+1,a+n+1); 103 Build(root,0,0,n+1); 104 F(i,1,n){ 105 int t1=findmin(root); 106 splay(kth(root,t1)); 107 printf("%d",t1-1); if(i!=n)printf(" "); 108 splay(kth(root,t1+1)); splay(kth(root,i),root); 109 int pos=c[c[root][0]][1]; 110 if (pos) rev[pos]^=1; 111 splay(pos); 112 } 113 return 0; 114 } 115
1552: [Cerc2007]robotic sort
Time Limit: 5 Sec Memory Limit: 64 MB
Submit: 436 Solved: 186
[Submit][Status][Discuss]
Description
Input
输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000。第二行为N个用空格隔开的正整数,表示N个物品最初排列的编号。
Output
输出共一行,N个用空格隔开的正整数P1,P2,P3…Pn,(1 < = Pi < = N),Pi表示第i次操作前第i小的物品所在的位置。
注意:如果第i次操作前,第i小的物品己经在正确的位置Pi上,我们将区间[Pi,Pi]反转(单个物品)。
Sample Input
6
3 4 5 1 6 2
Sample Output
4 6 4 5 6 6
HINT
Source
时间: 2024-10-19 23:53:28