题解—简单的填数
其实,改这到题之前,一切都很顺利。
很麻烦,所以这个应该慢慢想。
所以,改的东西出毛病了,不能着急,需要静下心来想一想。
该了一下午加一晚上就很亏。
这个东西,就是设计一个跳得快的数组,一个慢的。
分别记录他们的值和有几个连续的。
如果\(a[i]\)没有值,那么很简单,按照题意转移就行了。
如果有值
- 如果这个值很快的或者慢的的上一个值相等,直接继承过来加一。
- 如果不相等,进行分类讨论。
-
- 如果是慢的,因为要尽量让他慢,所以直接设成1
-
- 如果是快的,因为想要让他快点,所以我们想把它设置成2,这样他就能更快的扩展,但是如果出现一下情况,我们就只能让他是\(1\)。
想一想为什么我们可以直接设置成\(2\), 是因为之前快的跑的太快了,所以导致他到达一个有\(a[i]\)的数字的时候,他自身的值大于\(a[i]\)
导致他有一些值是浪费的。
所以直接设置成\(2\),可以利用他的一些浪费的,让他跑的更快。
但是,出现以下情况,只能是\(1\)。
- 上一个\(a[i]\)有数,并且是这个\(a[i]-1\)
- 上一个\(a[i]\)没数,上一个\(up[i]\)正好是这个\(a[i]-1\)
第一个很好理解,上一个被强迫是\(a[i]-1\)了,他这只能是新开的一个
第二个也还行,因为上一个\(a[i]\)没数,他都只能到\(a[i]-1\),说明之前没浪费也只能到这,所以也是新开的一个。
然后就行了。
输出方案,题解做法就是因为快的肯定对于他和她之前的的数是合法的,所以利用这个性质倒退
因为我是自己说服我自己的,所以具体为什么我也懒得写了。
\(dfs\)可以过,所以这里还是贴一个\(dfs\)的码吧。
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <assert.h>
#define R register int
#define int long
#define scanf Ruusupuu = scanf
#define printf Ruusupuu = printf
int Ruusupuu ;
using namespace std ;
typedef long long L ;
typedef long double D ;
typedef pair< int , int > PI ;
const int N = 2e5 + 10 ;
inline int read(){
int w = 0 ; bool fg = 0 ; char ch = getchar() ;
while( ch < '0' || ch > '9' ) fg |= ( ch == '-' ) , ch = getchar() ;
while( ch >= '0' && ch <= '9' ) w = ( w << 1 ) + ( w << 3 ) + ( ch - '0' ) , ch = getchar() ;
return fg ? -w : w ;
}
int n , a [N] , lo [N] , sh [N] , lpos [N] , spos [N] , cnt , vz [N] , cx [N] , ans [N] ;
inline void die(){ puts( "-1" ) , exit( 0 ) ; }
void sc(){
n = read() ; for( R i = 1 ; i <= n ; i ++ ){
a [i] = read() ;
if( a [i] ) vz [++ cnt] = i ;
}
if( a [1] && a [1] != 1 ) die() ;
for( R i = 1 ; i <= n ; i ++ ){
if( a [i] && a [i - 1] && a [i] < a [i - 1] ) die() ;
if( a [i] && a [i - 1] && a [i + 1] && a [i] != a [i - 1] && a [i] != a [i + 1] ) die() ;
} //先保证原序列合法(并没卵用)
}
inline void pf(){
for( R i = 1 ; i <= n ; i ++ ) printf( "%ld " , ans [i] ) ;
exit( 0 ) ;
}
void dfs( int x ){
if( x == n + 1 ){
if( ans [n] == a [n] && cx [ans [n]] >= 2 ) pf() ;
else return ;
} //printf( "%ld %ld %ld %ld %ld %ld %ld %ld\n" , x , ans [1] , ans [2] , ans [3] , ans [4] , ans [5] , ans [6] , ans [7] ) ;
int t = ans [x - 1] ;
if( a [x] ){
if( ( t == a [x] - 1 && cx [t] == 1 ) || ( t + 1 < a [x] ) ) return ;
ans [x] = a [x] , cx [a [x]] ++ , dfs( x + 1 ) , cx [a [x]] -- ;
}
else if( cx [t] == 1 ) ans [x] = ans [x - 1] , cx [ans [x]] ++ , dfs( x + 1 ) , cx [ans [x]] -- ;
else if( cx [t] == 5 ) ans [x] = ans [x - 1] + 1 , cx [ans [x]] ++ , dfs( x + 1 ) , cx [ans [x]] -- ;
else{
ans [x] = ans [x - 1] , cx [ans [x]] ++ , dfs( x + 1 ) , cx [ans [x]] -- ;
ans [x] = ans [x - 1] + 1 , cx [ans [x]] ++ , dfs( x + 1 ) , cx [ans [x]] -- ;
}
}
void work(){
lo [1] = lpos [1] = sh [1] = spos [1] = 1 ;
for( R i = 2 ; i <= n ; i ++ ){
// printf( "%ld %ld %ld %ld %ld\n" , lo [i - 1] , lpos [i - 1] , sh [i - 1] , spos [i - 1] , a [i] ) ;
if( a [i] ){
if( lo [i - 1] < a [i] && lpos [i - 1] < 2 ) die() ;
if( sh [i - 1] > a [i] ) die() ;
if( sh [i - 1] == a [i] && spos [i - 1] == 5 ) die() ;
lo [i] = sh [i] = a [i] ;
// printf( "%ld %ld %ld\n" , lo [i - 1] , sh [i - 1] , a [i] ) ;
spos [i] = ( ( sh [i - 1] == a [i] ) ? ( spos [i - 1] + 1 ) : ( 1 ) ) ;
// lpos [i] = max( spos [i] , ( ( lo [i - 1] == a [i] ) ? ( lpos [i - 1] + 1 ) : ( 1 ) ) ) ;
lpos [i] = ( ( lo [i - 1] == a [i] ) ? ( lpos [i - 1] + 1 ) : ( ( ( a [i - 1] + 1 == a [i] ) && ( a [i - 1] ) ) || ( !a [i - 1] && ( lo [i - 1] == a [i] - 1 ) ) ) ? 1 : 2 ) ;
// printf( "%ld %ld\n" , lpos [i] , spos [i] ) ;
}
else{
if( lpos [i - 1] >= 2 ) lpos [i] = 1 , lo [i] = lo [i - 1] + 1 ;
else lpos [i] = lpos [i - 1] + 1 , lo [i] = lo [i - 1] ;
if( spos [i - 1] == 5 ) spos [i] = 1 , sh [i] = sh [i - 1] + 1 ;
else spos [i] = spos [i - 1] + 1 , sh [i] = sh [i - 1] ;
}
// printf("%ld %ld %ld %ld\n",lo[i],lpos[i],sh[i],spos[i]);
} a [n] = lpos [n] >= 2 ? lo [n] : lo [n] - 1 ;
printf( "%ld\n" , a [n] ) ;
ans [1] = 1 , cx [1] ++ , dfs( 2 ) ;
for( R i = 1 ; i <= n ; i ++ ) printf( "%ld " , ans [i] ) ;
}
signed main(){
sc() ;
work() ;
return 0 ;
}
$The \ light \ has \ betrayed \ me$

浙公网安备 33010602011771号