9.31理論をフェッチ

問題の意味

定義された長さ\(N \)整数のシーケンス(\ \ {a_iを\} \ ) の動作は次のとおりです。一番左の列の選択(\ / \)右端の要素を、それを削除します

\(A \)\(B \)回転シーケンス\(Nは\)によって操作される\(\)上ハンド。以下の場合には一つだけの要素\(のx \) ゲームオーバーです。私たちは、このゲームの出力定義\(X- \を)\(\)出力にできるだけ大きくしたい、と\(Bの\)は可能な限り小さくしたいです

ゲームを開始する前に、\(\)は、正確ました\(K \)このシリーズのチャンスはより有利な状況を取得するために自分で操作します

とき(\)を\\(B \)がゲームをプレイする際に最適な戦略に従っている、ゲームの出力値はどのくらいになります

\(K = 0 \ 1-N \する)、回答を算出


ソリューション

JackAndRoseのアップグレード

そして質問はほとんど同じであることを具体的な証拠

主な困難は、である\(N = 0〜\ K -1 \) の回答に対応する計算され、それぞれの場合において

私たちは、たったの約その中心点と隣接点までの値の範囲のための答えを見つけることができます(異なるパリティがあります)

ですから、各サブパリティ処理中心点への答え

我々は、延出部の長さとして、中央部が拡大する両側に設定されていることが観察され

これは、新しい統計解答する前に得られた情報を使用するように私たちを触発しました

情報転送のパリティを用いて繰り返し点は、複雑さを行うことができる(\)O(N)\を


コード

(これはサブサブタスクに、ので、少し肥大化コード)

#include <cstdio>
#include <iostream>
#include <algorithm>

using namespace std;

int N, K;

int a[200100];

namespace sub1 {

int f[2010][2010][2];

int calc(int k) {
    int res = 0;
    for (int i = 0; i <= k; ++i)
        res = max(res, f[1 + i][N - k + i][0]);
    return res; 
}

void solve() {
    for (int i = 1; i <= N; ++i)  f[i][i][0] = f[i][i][1] = a[i];
    for (int i = 2; i <= N; ++i)
        for (int j = 1; j + i - 1 <= N; ++j) {
            int l = j, r = j + i - 1;
            f[l][r][0] = max(f[l + 1][r][1], f[l][r - 1][1]),
            f[l][r][1] = min(f[l + 1][r][0], f[l][r - 1][0]);
        }
    
    if (K != -1)
        printf("%d\n", calc(K));
    else {
        for (int i = 0; i < N; ++i)  
            printf("%d%c", calc(i), " \n"[i == N - 1]); 
    }
}

}

namespace sub2 {

int f[200100], g[200100], ans[200100];

void solve() {
    
    f[1] = a[1], f[N] = a[N];
    for (int i = 2; i < N; ++i) {
        int tmp = max(a[i - 1], max(a[i], a[i + 1]));
        if (a[i] == tmp)
            f[i] = max(a[i - 1], a[i + 1]);
        else
            f[i] = a[i];    
    }
    
    for (int i = 1; i < N; ++i)
        g[i] = max(a[i], a[i + 1]);
    
    if (N & 1) { 
    
        int l = (N + 1) / 2, r = (N + 1) / 2, sum = f[l];
        ans[0] = sum;
    
        for (int i = 2; i < N; i += 2) {
            l--, r++;
            sum = max(sum, max(f[l], f[r]));    
            ans[i] = sum;
        } 
    
        l = N / 2, r = N / 2 + 1, sum = 0;
        for (int i = 1; i < N; i += 2) {
            sum = max(sum, max(g[l], g[r]));
            l--, r++;
            ans[i] = sum;
        }
    } else {
        
        int l = N / 2, r = N / 2, sum = g[l];
        ans[0] = sum;
                
        for (int i = 2; i < N; i += 2) {
            l--, r++;
            sum = max(sum, max(g[l], g[r]));
            ans[i] = sum;
        }
        
        l = N / 2, r = N / 2 + 1, sum = 0;
        for (int i = 1; i < N; i += 2) {
            sum = max(sum, max(f[l], f[r]));
            l--, r++;
            ans[i] = sum;   
        }
    }
    
    ans[N - 1] = *max_element(a + 1, a + N + 1);
    
    if (K == -1)
        for (int i = 0; i < N; ++i)  printf("%d%c", ans[i], " \n"[i == N - 1]); 
    else
        printf("%d\n", ans[K]);
    
}
}

int main() {
    
//  freopen("game.in", "r", stdin);
//  freopen("game.out", "w", stdout);
    
    scanf("%d%d", &N, &K);
    
    for (int i = 1; i <= N; ++i)  scanf("%d", a + i);
    
    if (N <= 2000) 
        sub1::solve();
    else
        sub2::solve();
    
    return 0;
}

おすすめ

転載: www.cnblogs.com/VeniVidiVici/p/11616152.html