1. 程式人生 > >Codeforces Round #522 (Div. 2, based on Technocup 2019 Elimination Round 3) C

Codeforces Round #522 (Div. 2, based on Technocup 2019 Elimination Round 3) C

題意:給你一個長度為n的序列a,根據序列a,按照如下要求構造序列b:

1:若a【i】  > a【i+1】 則,b【i】 > b【i+1】

1:若a【i】  < a【i+1】 則,b【i】 < b【i+1】

1:若a【i】  = a【i+1】 則,b【i】 != b【i+1】

b【i】取值範圍為【1,5】,n的範圍為2e5.

輸出序列b。若構造不出來輸出-1

題解:因為需要列印路徑,所以定義dp【i】【j】表示b序列中第 i 位置為 j 的上一個位置是幾。然後從n位置遞迴找出一條可行的序列。

程式碼如下:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 +10;
int A[maxn];
int dp[maxn][10];
int main(){
    int n;
    cin >> n;
    for(int i = 1 ; i <= n ; i ++)
        cin >> A[i];
    memset(dp,-1,sizeof(dp));
    for(int i = 1 ; i <= 5 ; i ++){  // 初始化
        dp[1][i] = i;
    }
    for(int i = 2 ;  i <= n ; i ++){
        for(int j = 1 ; j <= 5 ; j ++){
            if(A[i] > A[i-1]){ 
                for(int k = 1 ; k < j ; k ++){
                    if(dp[i-1][k] >= 0){
                        dp[i][j] = k;
                    }
                }
            }
            else if(A[i] < A[i-1]){
                for(int k = j + 1; k <= 5 ; k ++){
                    if(dp[i-1][k] >= 0)
                        dp[i][j] = k;
                }
            }
            else {
                for(int k = 1 ; k <= 5 ; k ++){
                    if(k != j && dp[i-1][k] >= 0)
                        dp[i][j] = k;
                }
            }
        }
    }
    int start = -1;
    stack<int> s;
    for(int j = 1 ; j <= 5 ; j ++){
        if(dp[n][j] >= 0){
            s.push(j);
            start = j;
            break;
        }
    }
    if(start == -1){
        cout << -1;
        return 0;
    }
    for(int i = n ; i >= 2 ; i --){
        s.push(dp[i][start]);
        start = dp[i][start];
    }
    while(!s.empty()){
        cout << s.top() << " ";
        s.pop();
    }
    return 0;
}