人类题解 GET!
观察到 \(M\) 限制在 \(n \log n +n\) 左右,直接想到归并排序。
考虑合并过程:由于操作容器是栈,所以合并一次后,顺序会改变(升序变降序,降序变升序)。用代码用 op 记一下当前要升序或是降序。
两个有序的栈合并后一定在第三个栈里,且这样合并保底花 \(len\) 次操作,不可能更小了。主定理算一下发现已经是 \(T(n)=2T(n/2)+n=n\log n\),上限到了,不能用额外的操作去切分了。
其实往本质想,这个过程是递归嘛,处理其中一半时,另一半可以完全不管,只要排序后不压在其上,中间过程三栈都可以看成空的。
于是对于每次递归,只要钦定了终点,递归两个小区间的终点都是确定的了,然后做完了。
注意一下 \(len\) 为 \(1\) 的边界即可,细节不多。
实测极限都是 \(4818\) 此操作,比标程 \(4830\) 少一点。
Link
:::info[Code]
#include
#define int long long
using namespace std;
const int N=5e2+5;
int n,m;
array,3> a;
vector > ans;
int mgsort(int u,int v,int len,int op){if(len==1){if(u!=v){ans.push_back(make_pair(u,v));a[v].push_back(a[u].back());a[u].pop_back();}return v;}int l=len/2,r=len-l;int w=(u==v?(u+1)%3:3-u-v);// for(int i=1;i<=r;i++){// ans.push_back(make_pair(u,w));// a[w].push_back(a[u].back());// a[u].pop_back();// }// int p=mgsort(w,w,r,op^1);int p=mgsort(u,w,r,op^1);int q=mgsort(u,3-v-w,l,op^1);assert(p!=q);// cout<>n>>m;for(int i=1;i<=n;i++){int u;cin>>u;a[0].push_back(u);}array,3> b=a;int u=mgsort(0,0,a[0].size(),1);cout<
:::