Solution
考虑已知一个排列 \(p\) 怎么推出 \(c\),显然是维护差分标记 \(t\),对于 \(p_i,p_{i+1}\),给 \(t_{\min(p_i,p_{i+1})}\gets t_{\min(p_i,p_{i+1})}+1\) 以及 \(t_{\max(p_i,p_{i+1})}\gets t_{\max(p_i,p_{i+1})}-1\)。
显然可以从 \(c\) 简单推出 \(t\)。下面我们只讨论 \(i\in [2,n-1]\)。由于每个点只会被操作两次(到达一次,出发一次),则只可能存在 \(t_i\in \{-2,0,2\}\),且 \(\sum t_i=0\),即 \(-2\) 的个数 与 \(2\) 的个数相等。
考虑若 \(t_i=-2\),则两次操作这个点,\(i\) 都是作为终点,即 \(i\) 的左右两侧相邻的数都比 \(i\) 小;同理 \(t_i=2\) 表示两侧都比 \(i\) 大;\(t_i=0\) 表示一侧比 \(i\) 大,一侧比 \(i\) 小。
然后你会发现由于 \(c_i\) 为正,\(t_i\) 的每一个前缀和(从 \(2\) 开始)都是非负,所以第一个 \(2\) 一定在第一个 \(-2\) 之前,第二个 \(2\) 一定在第二个 \(-2\) 之前……然后就有一个很好的构造,把 \(1\) 放第一个,再放第一个 \(t_i=-2\) 的 \(i\),放第一个 \(t_i=2\) 的 \(i\),放第二个 \(t_i=-2\) 的 \(i\),以此类推,不难发现一定满足要求。
什么?你问 \(t_i=0\) 怎么办?在任意两个数 \(p_i,p_{i+1}\) 之间插 \([p_i,p_{i+1}]\) 里面(或 \([p_{i+1},p_i]\) 里面)的数就行。随便用 set 搞一下即可。
代码里还缝了一个 checker。
Code
#include<bits/stdc++.h>
using namespace std;
namespace Z3k7223{const int N=2e5+10;int n;int ip[N],a[N];int ans[N],vis[N],tot;int tg_chk[N];void check1(){for(int i=1;i<n;i++){int x=ans[i],y=ans[i+1];if(x>y){swap(x,y);}++tg_chk[x],--tg_chk[y];}sort(ans+1,ans+1+n);for(int i=1;i<=n;i++){if(ans[i]!=i){cerr<<"NOT A PERMUTATION!\n";return;}}for(int i=1;i<n;i++){tg_chk[i]+=tg_chk[i-1];}int cnt=0;for(int i=1;i<n;i++){if(tg_chk[i]!=ip[i]){++cnt;}}cerr<<cnt<<" error(s) found\n";}int tag[N];set<int>s;void ins(int x){if(s.empty()){ans[++tot]=x;return;}vector<int>tmp;if(ans[tot]>x){auto it=s.lower_bound(ans[tot]);while(it!=s.begin()){--it;if(*it<x)break;ans[++tot]=*it;tmp.push_back(*it);}}else{auto it=s.lower_bound(ans[tot]);while(it!=s.end()){if(*it>x)break;ans[++tot]=*it;tmp.push_back(*it);++it;}}for(int r:tmp){s.erase(r);}ans[++tot]=x;}void main(){cin>>n;for(int i=1;i<n;i++){cin>>ip[i];}for(int i=1;i<=n;i++){a[i]=ip[i]-ip[i-1];ans[i]=i;if(a[i]==0){s.insert(i);}}vector<int>ar,br;for(int i=1;i<=n;i++){if(a[i]==-2){ar.push_back(i);}if(a[i]==2){br.push_back(i);}}ans[++tot]=1;for(int i=0;i<ar.size();i++){ins(ar[i]);ins(br[i]);}for(int i=1;i<=n;i++){cout<<ans[i]<<' ';}cout<<'\n';check1();}
}
int main(){Z3k7223::main();return 0;
}