「2019 JizhongトレーニングDay9」問題解決レポート

\(フラグ\) 制服ブログ形式(クッション)

T1は、格子縞を取ります

\(N \回M \( 4 \当量のN、Mの\当量500)\) 行列、行列四つの要素がある:壁( "#")、空間領域( '' ")、開始点(" C「)、終了点(」F「)。
送信ガン操作がある:四の方向のいずれの方向にショットは、遭遇した最初の壁にポータルが存在するであろう、両者の存在のみが同時に送信しますすでに2つのポータルがある場合は、ドア、ポータルが消滅の最初のショットを表示され、操作は時間を消費しません。
それぞれが隣接するグリッドに移動することができ、出発点から移動すると、またはポータルの壁を持っていますポータルによって、隣接するグリッド(ポータルは、2つ存在しなければならない)、両方の操作が壁に移動し、単位時間を消費することができず、グリッドに隣接する他の転送ゲートに移動
開始から終了まで少なくともいくつかの時間がかかる単位。
マップのエッジを保証する円形の壁です。

\(ソル\)

銃の使用を転送:4つの壁は、最近の戦い側と反対側に、最近ポータルを通じて行った側を打つことができます。
最短とすることができます。

時間複雑\(O \ビッグ(NM \ log_2(nm)を\ビッグ)\)

\(出典\)

//#pragma GCC Optmize(2)
//#pragma GCC Optmize(3, "Ofast", "inline")
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
int in() {
    int x = 0; char c = getchar(); bool f = 0;
    while (c < '0' || c > '9')
        f |= c == '-', c = getchar();
    while (c >= '0' && c <= '9')
        x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    return f ? -x : x;
}
template<typename T>inline void chk_min(T &_, T __) { _ = _ < __ ? _ : __; }
template<typename T>inline void chk_max(T &_, T __) { _ = _ > __ ? _ : __; }

const int N = 505;

char mp[N][N];

struct link {
    int l, r, u, d;
} nxt[N][N];

int n, m, d[N][N];
int dx[] = {1, 0, -1, 0};
int dy[] = {0, 1, 0, -1};
bool vis[N][N];
typedef std::pair<int, int> pii;
typedef std::pair<int, pii> pip;

int dijkstra() {
    std::priority_queue<pip> q;
    int ex, ey;
    memset(d, 0x3f, sizeof(d));
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= m; ++j) {
            if (mp[i][j] == 'C')
                q.push(pip(0, pii(i, j))), d[i][j] = 0;
            if (mp[i][j] == 'F')
                ex = i, ey = j;
        }
    while (!q.empty()) {
        int nx = q.top().second.first, ny = q.top().second.second, tx, ty, tmp; q.pop();
        if (vis[nx][ny])
            continue;
        vis[nx][ny] = 1;
        if (nx == ex && ny == ey)
            return d[nx][ny];
        for (int i = 0; i < 4; ++i) {
            tx = nx + dx[i], ty = ny + dy[i];
            if (mp[tx][ty] == '#' || d[nx][ny] + 1 >= d[tx][ty])
                continue;
            d[tx][ty] = d[nx][ny] + 1;
            q.push(pip(-d[tx][ty], pii(tx, ty)));
        }
        tmp = ny - nxt[nx][ny].l;
        chk_min(tmp, nx - nxt[nx][ny].u);
        chk_min(tmp, nxt[nx][ny].r - ny);
        chk_min(tmp, nxt[nx][ny].d - nx);
        ++tmp;

        tx = nx, ty = nxt[nx][ny].l;
        if (ny - ty > tmp && d[tx][ty] > d[nx][ny] + tmp)
            d[tx][ty] = d[nx][ny] + tmp, q.push(pip(-d[tx][ty], pii(tx, ty)));
        tx = nx, ty = nxt[nx][ny].r;
        if (ty - ny > tmp && d[tx][ty] > d[nx][ny] + tmp)
            d[tx][ty] = d[nx][ny] + tmp, q.push(pip(-d[tx][ty], pii(tx, ty)));
        tx = nxt[nx][ny].u, ty = ny;
        if (nx - tx > tmp && d[tx][ty] > d[nx][ny] + tmp)
            d[tx][ty] = d[nx][ny] + tmp, q.push(pip(-d[tx][ty], pii(tx, ty)));
        tx = nxt[nx][ny].d, ty = ny;
        if (tx - nx > tmp && d[tx][ty] > d[nx][ny] + tmp)
            d[tx][ty] = d[nx][ny] + tmp, q.push(pip(-d[tx][ty], pii(tx, ty)));
    }
    return -1;
}

int main() {
    //freopen("in", "r", stdin);
    freopen("cell.in", "r", stdin);
    freopen("cell.out", "w", stdout);
    n = in(), m = in();
    memset(nxt, -1, sizeof(nxt));
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= m; ++j)
            while (mp[i][j] != '.' && mp[i][j] != 'C' && mp[i][j] != 'F' && mp[i][j] != '#')
                mp[i][j] = getchar();
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= m; ++j) {
            if (mp[i][j] == '#')
                continue;
            if (mp[i - 1][j] != '#')
                nxt[i][j].u = nxt[i - 1][j].u;
            else
                nxt[i][j].u = i;
            if (mp[i][j - 1] != '#')
                nxt[i][j].l = nxt[i][j - 1].l;
            else
                nxt[i][j].l = j;
        }
    for (int i = n; i; --i)
        for (int j = m; j; --j) {
            if (mp[i][j] == '#')
                continue;
            if (mp[i + 1][j] != '#')
                nxt[i][j].d = nxt[i + 1][j].d;
            else
                nxt[i][j].d = i;
            if (mp[i][j + 1] != '#')
                nxt[i][j].r = nxt[i][j + 1].r;
            else
                nxt[i][j].r = j;
        }
    int res = dijkstra();
    if (!~res)
        puts("no");
    else
        printf("%d\n", res);
    return 0;
}

T2、ねじれの数

有すること\(キー\(1 \当量のキーの\当量10 ^ {18})\) キーであり、\(ヴァル\(^ 10 1当量6 1 \のLeqヴァル\)は\)重み値である\(BST \) 各ノード示さ\(SUM \)は、ルートとそのサブツリーにある\(ヴァル\)合計。所与\(N \(1 \当量のn \の当量300)\) ポイント\(キー\)\(ヴァル\) 木の端に任意の2点を確保する必要\(キー\)がありませんプライムシーク\(SUM \)の最大値の合計を。木の法的形式、出力がない場合、\は(--1 \)

\(ソル\)

間隔考える\(DP \)を今押し、シーケンス(キー\)\を付し、ソート(F_ {I、J、\ 0/1} \) の間隔を表す\([I、J]を\ ) として使用することができる\(I 1(0で表される)/((1)で表される)は、i + 1 \) -サブツリーの最大\(SUM \)と、暴力を転送します。
\(F_ {I、J、 0} \) :例(境界を考慮せずに)
{。。 - 1 ^ {J} 1} \ {F_ [F_ {I、Jは、} 0 \ = I + KのMAX_は= \ {I、K - 1,1} +
F_ {K + 1、J、0} +和[I、J] \} \] 時間複雑度\(O(N ^ 3)\)

\(出典\)

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
int in() {
    int x = 0; char c = getchar(); bool f = 0;
    while (c < '0' || c > '9')
        f |= c == '-', c = getchar();
    while (c >= '0' && c <= '9')
        x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    return f ? -x : x;
}
long long lin() {
    long long x = 0; char c = getchar(); bool f = 0;
    while (c < '0' || c > '9')
        f |= c == '-', c = getchar();
    while (c >= '0' && c <= '9')
        x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    return f ? -x : x;
}
template<typename T>inline void chk_min(T &_, T __) { _ = _ < __ ? _ : __; }
template<typename T>inline void chk_max(T &_, T __) { _ = _ > __ ? _ : __; }

const int N = 305;

int n, sum[N], id[N];
long long key[N], tmp[N], f[N][N][2];
bool mp[N][N];

long long gcd(long long _, long long __) {
    return __ ? gcd(__, _ % __) : _;
}

inline bool cmp(const int &i, const int j) {
    return key[i] < key[j];
}

void init() {
    for (int i = 1; i <= n; ++i)
        id[i] = i;
    std::sort(id + 1, id + 1 + n, cmp);
    for (int i = 1; i <= n; ++i)
        tmp[i] = key[id[i]];
    for (int i = 1; i <= n; ++i)
        key[i] = tmp[i];
    for (int i = 1; i <= n; ++i)
        tmp[i] = sum[id[i]];
    for (int i = 1; i <= n; ++i)
        sum[i] = sum[i - 1] + tmp[i];
    for (int i = 0; i < n; ++i)
        for (int j = i + 1; j <= n; ++j)
            mp[i][j] = gcd(key[i], key[j]) > 1;
}

int main() {
    //freopen("in", "r", stdin);
    freopen("tree.in", "r", stdin);
    freopen("tree.out", "w", stdout);
    n = in();
    for (int i = 1; i <= n; ++i)
        key[i] = lin(), sum[i] = in();
    init(); 
    for (int i = 1; i <= n; ++i) {
        if (mp[i - 1][i])
            f[i][i][0] = sum[i] - sum[i - 1];
        if (mp[i][i + 1])
            f[i][i][1] = sum[i] - sum[i - 1];
    }
    for (int len = 2; len <= n; ++len) {
        for (int i = 1; i + len - 1 <= n; ++i) {
            int j = i + len - 1;
            if (f[i + 1][j][0]) {
                if (mp[i - 1][i])
                    chk_max(f[i][j][0], f[i + 1][j][0] + sum[j] - sum[i - 1]);
                if (mp[i][j + 1])
                    chk_max(f[i][j][1], f[i + 1][j][0] + sum[j] - sum[i - 1]);
            }
            if (f[i][j - 1][1]) {
                if (mp[i - 1][j])
                    chk_max(f[i][j][0], f[i][j - 1][1] + sum[j] - sum[i - 1]);
                if (mp[j][j + 1])
                    chk_max(f[i][j][1], f[i][j - 1][1] + sum[j] - sum[i - 1]);
            }
            for (int k = i + 1; k < j; ++k) {
                if (mp[i - 1][k] && f[i][k - 1][1] && f[k + 1][j][0])
                    chk_max(f[i][j][0], f[i][k - 1][1] + f[k + 1][j][0] + sum[j] - sum[i - 1]);
                if (mp[k][j + 1] && f[i][k - 1][1] && f[k + 1][j][0])
                    chk_max(f[i][j][1], f[i][k - 1][1] + f[k + 1][j][0] + sum[j] - sum[i - 1]);
            }
        }
    }
    if (f[1][n][0])
        printf("%lld\n", f[1][n][0]);
    else
        puts("-1");
    return 0;
}

T3、サブセグメントの回転

長所与(\ N-)\を配置\(\ {a_iを\} \) サブインターバルを反転することができ、要求部フリップフロッ\を(私は\)位置の数が等しい(Iは\)\の最大数。

\(ソル\)

およそエンドポイントのフリップ範囲は、原因の貢献を持つエンドポイントに関する列挙検討し、迅速貢献フリップ間隔を計算する必要があります。
順不同の数のいずれかのことに注意してください\((I、a_iを)\) およびそれが短い間隔に貢献するよりも多くないに等しいだけ回転中心で、の長さに応じて、一緒にランダムな数に等しく、すべての回転中心を置くことが可能です小規模から大規模な列挙への需要を満たすために。

時間複雑\(O(N)\)

ソース:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
int in() {
    int x = 0; char c = getchar(); bool f = 0;
    while (c < '0' || c > '9')
        f |= c == '-', c = getchar();
    while (c >= '0' && c <= '9')
        x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    return f ? -x : x;
}
template<typename t>inline void chk_min(t &_, t __) { _ = _ < __ ? _ : __; }
template<typename t>inline void chk_max(t &_, t __) { _ = _ > __ ? _ : __; }

const int N = 1e5 + 5;

int n, a[N], p[N], pre[N];

typedef std::pair<int, int> pii;
std::vector<pii> s[N << 1];

int main() {
    //freopen("in", "r", stdin);
    freopen("rotate.in", "r", stdin);
    freopen("rotate.out", "w", stdout);
    n = in();
    for (int i = 1; i <= n; ++i)
        a[i] = in(), p[a[i]] = i, pre[i] = pre[i - 1] + (a[i] == i);
    for (int i = 1; i <= n; ++i) {
        if (a[i] <= i)
            s[i + a[i]].push_back(pii(i, a[i]));
        if (p[i] < i)
            s[i + p[i]].push_back(pii(i, p[i]));
    }
    int res = pre[n];
    for (int i = 1; i <= n + n; ++i)
        for (unsigned j = 0; j < s[i].size(); ++j)
            chk_max(res, (int)j + 1 + pre[s[i][j].second - 1] + pre[n] - pre[s[i][j].first]);
    printf("%d\n", res);
    return 0;
}

おすすめ

転載: www.cnblogs.com/15owzLy1-yiylcy/p/11329391.html