一开始想的是利用归并排序的原理将n个数分开再两两合并。
之后发现用基数排序的方法也可以,不过是把a[i]离散化之后再看成2进制后使用归并排序,因为看成2进制之后每个树都可以根据这一位01是什么分到2,3两个栈。
基数排序
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const int N=210000; int read(){ int sum=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){sum=sum*10+ch-'0';ch=getchar();} return sum*f; } pair<int,int> p[N]; int stack_1[N],stack_2[N],stack_3[N],top_1,top_2,top_3,ans1[N],ans2[N],ans; int main(){ int n=read(); for(int i=1;i<=n;i++)stack_1[++top_1]=read(),p[i]=make_pair(stack_1[i],i); sort(p+1,p+1+n); for(int i=1;i<=n;i++)stack_1[p[i].second]=i; for(int i=1;i<=10;i++){ int bit=1<<(i-1); while(top_1){ if(stack_1[top_1]&bit)stack_2[++top_2]=stack_1[top_1--],ans1[++ans]=1,ans2[ans]=2; else stack_3[++top_3]=stack_1[top_1--],ans1[++ans]=1,ans2[ans]=3; } while(top_2)stack_1[++top_1]=stack_2[top_2--],ans1[++ans]=2,ans2[ans]=1; while(top_3)stack_1[++top_1]=stack_3[top_3--],ans1[++ans]=3,ans2[ans]=1; } printf("%d\n",ans); for(int i=1;i<=ans;i++)printf("%d %d\n",ans1[i],ans2[i]); return 0; }
归并排序
#include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; #define mid (L+R>>1) const int N=201000; int Size[N],stack_1[N],stack_2[N],stack_3[N],top_1,top_2,top_3,ans,ans_1[N],ans_2[N]; void update(int now){ Size[now]=Size[now*2]+Size[now*2+1]; } void dfs(int L,int R,int now){ if(L==R){ Size[now]=1; return; } dfs(L,mid,now*2); for(int i=1;i<=Size[now*2];i++)stack_2[++top_2]=stack_1[top_1--],ans_1[++ans]=1,ans_2[ans]=2; dfs(mid+1,R,now*2+1); for(int i=1;i<=Size[now*2+1];i++)stack_3[++top_3]=stack_1[top_1--],ans_1[++ans]=1,ans_2[ans]=3; int cnt_2=0,cnt_3=0; while(cnt_2<Size[now*2]&&cnt_3<Size[now*2+1]){ if(stack_2[top_2]>=stack_3[top_3])stack_1[++top_1]=stack_2[top_2--],ans_1[++ans]=2,ans_2[ans]=1,cnt_2++; else stack_1[++top_1]=stack_3[top_3--],ans_1[++ans]=3,ans_2[ans]=1,cnt_3++; } while(cnt_2<Size[now*2])stack_1[++top_1]=stack_2[top_2--],ans_1[++ans]=2,ans_2[ans]=1,cnt_2++; while(cnt_3<Size[now*2+1])stack_1[++top_1]=stack_3[top_3--],ans_1[++ans]=3,ans_2[ans]=1,cnt_3++; update(now); } int main(){ int n; scanf("%d",&n); for(int i=1;i<=n;i++){ int x; scanf("%d",&x); stack_1[++top_1]=x; } dfs(1,n,1); printf("%d\n",ans); for(int i=1;i<=ans;i++)printf("%d %d\n",ans_1[i],ans_2[i]); return 0; }