题目链接:点击打开链接
题目大意:给出一个序列,分成若干个置换群,要求最终的序列的字典序最大。
要求字典序最大,那么从1开始向后遍历,尽量放较大的数
给出序列a1 a2 a3 ,,, ai an
对于第i个数来说,可能有三种情况,第一种向前找能到达的序列的最大值ak,那么ak到ai就是一个轮换;第二种ai自身,或者是以ai结尾;第三种由i想后找,对于轮换来说,只能在i位置放ai+1,那么ai和ai+1只能构成轮换的一部分;在这三种可以放的值中选出最大值,也就是第i个位置能放的数
注意
1、当选自身是,可能是自己一个数为一个轮换,也可能是一个轮换的结尾,那么i位置要放这个轮换的第一个数。
2、对于第三种情况来说,只能确定轮换的一部分,不能确定一个完整的轮换,这些轮换的片段可以连接起来,并且可以通过第二种情况是轮换完整。
#include <cstdio>
#include <cstring>
#include <queue>
#include <set>
#include <vector>
#include <cmath>
#include <map>
#include <stack>
#include <algorithm>
using namespace std ;
#pragma comment(linker, "/STACK:102400000,102400000")
#define LL __int64
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
const int mod = 1e9+7 ;
const double eqs = 1e-9 ;
#define maxn 100000+10
#define root 1,n,1
#define int_rt int l,int r,int rt
#define lson l,(l+r)/2,rt<<1
#define rson (l+r)/2+1,r,rt<<1|1
int cl1[maxn<<2] , cl2[maxn<<2] ;
int a[maxn] , ans[maxn] , vis[maxn] , id[maxn] , flag[maxn];
void push_up1(int rt) {
cl1[rt] = max(cl1[rt<<1],cl1[rt<<1|1]) ;
return ;
}
void create(int_rt) {
if( l == r ) {
scanf("%d", &a[l]) ;
cl1[rt] = a[l] ;
id[ a[l] ] = l ;
return ;
}
create(lson) ;
create(rson) ;
push_up1(rt) ;
return ;
}
void update1(int k,int_rt) {
if( l == r ) {
cl1[rt] = -1 ;
return ;
}
if( (l+r)/2 >= k ) update1(k,lson) ;
else if( k > (l+r)/2 ) update1(k,rson) ;
else return ;
push_up1(rt) ;
}
int query1(int ll,int rr,int_rt) {
if( rr < l || ll > r ) return -1 ;
if( ll <= l && rr >= r ) return cl1[rt] ;
return max( query1(ll,rr,lson) , query1(ll,rr,rson) ) ;
}
void push_up2(int rt) {
cl2[rt] = max(cl2[rt<<1] , cl2[rt<<1|1]) ;
return ;
}
void update2(int k,int_rt) {
if( l == r ) {
cl2[rt] = l ;
return ;
}
if( k <= (l+r)/2 ) update2(k,lson) ;
else if( k > (l+r)/2 ) update2(k,rson) ;
else return ;
push_up2(rt) ;
return ;
}
int query2(int ll,int rr,int_rt) {
if( rr < l || ll > r ) return -1 ;
if( ll <= l && rr >= r ) return cl2[rt] ;
return max( query2(ll,rr,lson) , query2(ll,rr,rson) ) ;
}
int main() {
int t , n , i , j ;
int k1 , k2 , k3 ;
int l , r ;
//freopen("1012.in","r",stdin) ;
// freopen("23333.txt","w",stdout) ;
scanf("%d", &t) ;
while( t-- ) {
memset(cl1,-1,sizeof(cl1)) ;
memset(cl2,-1,sizeof(cl2)) ;
memset(vis,0,sizeof(vis)) ;
memset(flag,0,sizeof(flag)) ;
scanf("%d", &n) ;
create(root) ;
a[n+1] = -1 ;
for(i = 1 ; i <= n ; i++) {
if(i == 715)
i = 715 ;
if( vis[i] == 1 ) continue ;
l = query2(1,id[i]-1,root) ;
l++ ;
if( l <= 0 ) l = 1 ;
k1 = query1(l,id[i]-1,root) ;
if( vis[i] == 0 ) k2 = i ;
else if( vis[i] < 0 && !vis[ -vis[i] ] ) k2 = -vis[i] ;
else k2 = -1 ;
k3 = a[ id[i]+1 ] ;
if( vis[ a[ id[i]+1 ] ] == 1 ) k3 = -1 ;
if( k1 > k2 && k1 > k3 ) {
ans[i] = k1 ;
vis[k1] = 1 ;
for( j = id[k1] ; j < id[i] ; j++ ) {
ans[ a[j] ] = a[j+1] ;
vis[ a[j+1] ] = 1 ;
}
update2(id[i],root) ;
}
else if( k2 > k1 && k2 > k3 ) {
ans[i] = k2 ;
vis[ ans[i] ] = 1 ;
flag[ flag[ k2 ] ] = 0 ;
flag[k2] = 0 ;
update2(id[i],root) ;
}
else if( k3 > k1 && k3 > k2 ) {
if( vis[i] == 0 ) {
vis[ k3 ] = -i ;
ans[i] = k3 ;
flag[k3] = i ;
flag[i] = k3 ;
}
else {
if( flag[ k3 ] ) {
ans[i] = k3 ;
vis[ k3 ] = 1 ;
flag[ flag[k3] ] = flag[i] ;
flag[ flag[i] ] = flag[k3] ;
vis[ flag[k3] ] = vis[i] ;
continue ;
}
else{
flag[k3] = flag[i] ;
flag[flag[i]] = k3 ;
vis[k3] = vis[i] ;
ans[i] = k3 ;
}
}
update1(id[i],root) ;
update1(id[k3],root) ;
}
}
for(i = 1 ; i < n ; i++)
printf("%d ", ans[i]) ;
printf("%d\n", ans[n]) ;
}
return 0 ;
}