AtCoder初心者コンテスト137の解決レポート(A〜E)

:より転載https://lornd.top/index.php/archives/37/

ゲームのアドレス:AtCoder初級コンテスト137

- + -x

効果の対象に

二つの数を考えると、\(\)、\ (B \)それ、見つける\(A + B \) - \ (B \ A)、\ (\ Bタイムズ\)の最大値

問題解決のためのアイデア

#include <cstdio>
#include <algorithm>

int a, b;

int main() {
    scanf("%d%d", &a, &b);
    printf("%d", std::max(a + b, std::max(a - b, a * b)));
    return 0;
}

B - 一つの手がかり

効果の対象に

そこ(2000001 \)\行の石、番号( - 1000000 \)\する(1000000 \)を\連続前記\(K \) 石を黒染めされた座標\(X- \を)石は、石は黒染めされてもよいシークれ、黒です。

問題解決のためのアイデア

議論のポイントは、座標\(X \)石はこの中にあり、\(K \)どこでも石で、かつ一番左または右端に加えて、生成された残りの位置が左端または大部分に含まれている答え生成するために正しい答えの中で、これだけの数の石は黒染めすることができ、両方のケースで計算する必要があります。

#include <cstdio>

int k, x;

int main() {
    scanf("%d%d", &k, &x);
    for (int i = x - k + 1; i <= x + k - 1; ++i) {
        printf("%d ", i);
    }
    return 0;
}

C - グリーンビン

効果の対象に

列の定義\(\)別の文字列\(B \)パズルの、及び場合のみならば\(\)は、で作ることができる\(B \)組成所与を再配置(N \)\文字列、尋ねたどのように多くの\((i、j)は( I <jの)\) 最初に満たす\(私は\)最初の文字列\(J \)文字列の相互パズルを。

問題解決のためのアイデア

:問題の意味によると、私たちは、新たな2つの文字列が取得する場合にのみ、それはそれぞれの文字の後にソート例えば、同じであれば互いに2つの文字列が、パズル見ることができるgreenbinbeginnerパズル相互彼らはソートされた後ので、beeginnr文字列。

だから私たちは、このことができます(nは\)\文字列が全体的に、その後、このソートされている\(N \)同じ文字列のそれぞれをカウントし、その後、すぐに同じ文字列を取得するには、ソート文字列を右を見つけるために2つを取ることができますいずれかの数、\((I、J)\) いくつかの問題の組み合わせです。

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

const int MAXN = 1e5 + 5;

int n;
int tmp[MAXN], cnt;
long long int ans;
std::string s[MAXN];

int main() {
    std::cin >> n;
    for (int i = 1; i <= n; ++i) {
        std::cin >> s[i];
        std::sort(s[i].begin(), s[i].end());
    }
    std::sort(s + 1, s + n + 1);
    for (int i = 1; i <= n; ++i) {
        if (s[i] != s[i - 1])
            ++cnt;
        ++tmp[cnt];
    }
    for (int i = 1; i <= cnt; ++i) {
        ans += 1ll * tmp[i] * (tmp[i] - 1) >> 1;
    }
    std::cout << ans;
    return 0;
}

D - 夏休み

効果の対象に

そこ\(N \)動作モード、\は(私は\)動作モードを終了するために一日かかります、となります(a_iを\)\得るために、(一日の仕事を含む)の日を\(B_i \)の収入を、合計そこ(m個\)\最大の利益を求めて、日。

問題解決のためのアイデア

我々は同様に残して、逆方向に貪欲であるかもしれない\(1 \)日、残りの\(2 \)日......たびに、我々は、下の残りの部分を記録することができます(私は\)\収入を得るために仕事の日、そして利益を取りますプライオリティキューを完了するために直接使用することができる最大の仕事、。

#include <cstdio>
#include <queue>
#include <algorithm>

const int MAXN = 1e5 + 1;

int n, m, ans, cur;

struct job {
    int wait, val;

    job(int ww = 0, int vv = 0) {
        wait = ww;
        val = vv;
    }

    bool operator < (const job &another) const {
        return wait < another.wait;
    }
}arr[MAXN];

struct node {
    int key;

    node (int kk = 0) {
        key = kk;
    }

    bool operator < (const node &another) const {
        return key < another.key;
    }
};

std::priority_queue<node> q;

int main() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; ++i) {
        scanf("%d%d", &arr[i].wait, &arr[i].val);
    }
    std::sort(arr + 1, arr + n + 1);
    cur = 1;
    for (int i = 1; i <= m; ++i) {
        while (cur <= n && arr[cur].wait <= i) {
            q.push(node(arr[cur].val));
            ++cur;
        }
        if (!q.empty()) {
            ans += q.top().key;
            q.pop();
        }
    }
    printf("%d", ans);
    return 0;
}

E - コインの復活

効果の対象に

ある\(\ N-)点、\(Mの\)エッジがグラフ指向している\(Iは\)文書のエッジ\(C_I \)を収集するために繰り返すことができる硬貨は、。\(1 \)行ってきました\(N \)を(で、そして最後に)\(N \際続行を選択することができたとき、あなたはまた、最後に選択することができます支払うこと)(T \回P \)\これは、金貨を\(T \)エッジの数は、横断されます。残りは、コインの最大数、現在ほとんどない場合、出力要求\を(--1 \)

問題解決のためのアイデア

我々各\(C_Iが\)減算される\(P \)を得るために、\(D_Iを\) タイトルは、収集の各側の後、なった\(D_I \)金貨、端部における残りの最大数を依頼します金、つまり\(1 \)\(N- \)最長パス。

この図に有し、環を有することができるので、トポロジカルソート+ DPの方法を使用することができないが、我々は、緩和動作は変化の数が最長経路を得るために数より大きい未満でSPFAでき、一方、正の決意リング(誤解)同じ環上の方法と否定判定、回数チームへのその侵入(または上記の点\(N- \) ことができます。

点Nに達していないことにより環しかし、リングを表していない全く肯定的な解決策は、これは可能ではない\(\ N-)は、我々はまた、プレポイントに到達することができなければならない(N- \)\設定点を、次いで、唯一のポイントに達することができるようにするためSPFA時間\(N \)ポイントを、この前処理をすることができ、ビルドマップ逆から取得した、(N \)は\点を出発点に到達することができ、我々はその点を尋ねます。

#include <cstdio>
#include <vector>
#include <queue>
#include <algorithm>

const int MAXN = 1e5 + 5;

int n, m, p, u, v, k;
int dist[MAXN], num[MAXN];
bool flag[MAXN], inQueue[MAXN];

struct graph {
    int vertex, val;

    graph(int vv = 0, int vval = 0) {
        vertex = vv;
        val = vval;
    }
};

std::vector<graph> con[MAXN], reverse[MAXN];
std::queue<int> q;

void ins(int start, int end, int key, std::vector<graph> a[]) {
    a[start].push_back(graph(end, key));
}

void init(int key) {
    flag[key] = true;
    for (int i = 0; i < reverse[key].size(); ++i) {
        int nxt = reverse[key][i].vertex;
        if (flag[nxt] == false)
            init(nxt);
    }
}

int spfa() {
    for (int i = 2; i <= n; ++i) {
        dist[i] = -(1e9 + 7);
    }
    dist[1] = 0;
    q.push(1);
    inQueue[1] = true;
    while (!q.empty()) {
        int cur = q.front();
        q.pop();
        inQueue[cur] = false;
        for (int i = 0; i < con[cur].size(); ++i) {
            int nxt = con[cur][i].vertex, cost = con[cur][i].val;
            if (flag[nxt] && dist[nxt] < dist[cur] + cost) {
                dist[nxt] = dist[cur] + cost;
                if (!inQueue[nxt]) {
                    q.push(nxt);
                    inQueue[nxt] = true;
                    ++num[nxt];
                    if (num[nxt] > n)
                        return -1;
                }
            }
        }
    }
    return std::max(dist[n], 0);
}

int main() {
    scanf("%d%d%d", &n, &m, &p);
    for (int i = 1; i <= m; ++i) {
        scanf("%d%d%d", &u, &v, &k);
        ins(u, v, k - p, con);
        ins(v, u, 1, reverse);
    }
    init(n);
    printf("%d", spfa());
    return 0;
}

おすすめ

転載: www.cnblogs.com/lornd/p/11364564.html