题目:
给出一个数组,要求将数组改为没有局部最小值的数组。求最小操作次数和操作结果。
思路:
对每一个数,检测他是否比前一个数大,如果是,那么就将其标记,如果是,那么将他标记上。如果该数比之前的数小,那么就检测前一个数是否为局部最大值,如果是,就将该位置的数改为和前一个数等大,然后将改动的数也标记上。如果该数的前一个已经改过,而且该数又比前一个数大,那么就将前一个数改为这个数(反正改多一次也是只改一次)。然后该数就不需要再标记。
算法的时间复杂度为O( n )。
代码:
#include <bits/stdc++.h>
#define MaxN 200001
using namespace std;
int vis [ MaxN ]; // -1 means bigger than last
// 1 means changed
int linel[ MaxN ];
int main( ) {
int i, j, k;
int N, T;
int ans;
scanf("%d", &T );
while ( T-- ) {
ans = 0;
scanf("%d", &N );
scanf("%d", &linel[ 1 ] );
for ( i = 2; i <= N; i ++ ) {
scanf("%d", &linel[ i ] );
if ( i != 2 ) {
if ( linel[ i ] < linel[ i - 1 ] && vis[ i - 1 ] == -1) {
linel[ i ] = linel[ i - 1 ];
vis[ i ] = 1;
ans ++;
} else if ( linel[ i ] > linel[ i - 1 ] && vis[ i - 1 ] == 1 ) {
linel[ i - 1 ] = linel[ i ];
}
}
if ( linel[ i ] > linel[ i - 1 ] )
vis[ i ] = -1;
}
printf("%d\n", ans );
for ( i = 1; i <= N; i ++ ) {
printf("%d ", linel[ i ] );
vis[ i ] = 0;
}
putchar( '\n' ) ;
}
return 0;
}