AtCoderビギナーコンテスト188問題解決レポート

タイトルリンク:https//atcoder.jp/contests/abc188/tasks

A-3点シュート

トピック

x、yを与え、小さい方の値に3を加えたものが大きい方の値を超えることができるかどうかを尋ねます

アイデア

直接判断

ACコード

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main(){
    int x, y;
    cin >> x >> y;
    if(x > y) swap(x, y);
    if(x + 3 > y) cout << "Yes" << endl;
    else cout << "No" << endl;
    return 0;
}

B-直交性

トピック

2つの配列、対応する位置が乗算および合計されて、0に等しいかどうかが確認されます

アイデア

直接シミュレーション

ACコード

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 1e5 + 5;
int a[maxn], b[maxn];
int main(){
    int n; cin >> n;
    for(int i = 1; i <= n; i ++) cin >> a[i];
    for(int i = 1; i <= n; i ++) cin >> b[i];
    ll ans = 0;
    for(int i = 1; i <= n; i ++) ans += a[i] * b[i];
    if(ans == 0) cout << "Yes" << endl;
    else cout << "No" << endl; 
    return 0;
}

C-ABCトーナメント

トピック

nを与えてから、i番目の人のスコアを表す2 ^ nの数字を与えます。各ラウンドには2つのpkが隣接しています。スコアの高い方が勝ち、次のラウンドに入り、最初のラウンドを出力します。最終準優勝の添え字

アイデア

ベクトルシミュレーション

ACコード

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 1e5 + 5;
vector<pair<int, int>> a, b;
int main(){
    int n; cin >> n;
    for(int i = 1; i <= (1 << n); i ++) {
        int x; cin >> x;
        a.push_back({x, i});
    }
    for(int i = 1; i < n; i ++){
        for(int j = 0; j < a.size(); j += 2){
            if(a[j].first > a[j + 1].first) b.push_back(a[j]);
            else b.push_back(a[j + 1]);
        }
        a = b;
        b.clear();
    }
    if(a[0].first > a[1].first) cout << a[1].second << endl;
    else cout << a[0].second << endl;
    return 0;
}

D-スヌークプライム

トピック

高橋が遊びに行って、現在n個のアイテムを提供しています。時間は[ai、bi]で、これらのアイテムは毎日ciを費やす必要がありますが、この日に表示されるすべてのアイテムを再生するために1日C元を使うことを選択できます、彼はプレイする必要があります、彼に最小の支出を依頼します

たとえば、最初の例では、2つのアイテムがあり、1日に表示されるすべてのアイテムを再生するには6のコストがかかり、最初のアイテムは[1,2]に表示され、1日あたり4のコストがかかり、2番目のアイテムは[2,2]、1日あたりのコストは4です。つまり、最初の日は4を費やす必要があり、次の日は4 + 4 = 8を費やす必要がありますが、8 <6はプロジェクト1をプレイするために6元を費やすことを選択できます。 2なので、合計4 + 6 = 10

アイデア

違いは、その日の各アイテムのコストを計算することです。その後、1日のコストは、当日のコストとCの小さい方の値になります。

ACコード

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 2e5 + 5;
map<int, ll> mp; // 差分数组
//s表示差分的前缀和,表示到这天单付当天所有项目的花费
//last表示一个天数,(it.first - last)表示s价格出现的天数,也就是在这个期间价格不变
//x表示当天花的钱
//ans表示求的最小花费
int main(){
    ll n, c;
    cin >> n >> c;
    for(int i = 1; i <= n; i ++){
        ll x, y, w; 
        cin >> x >> y >> w;
        mp[x] += w; mp[y + 1] -= w; // 差分操作
    }
    ll s = 0, ans = 0;
    int last = 0;
    for(auto it : mp){
        ll x = min(s, c);
        ans += x * (it.first - last);
        s += it.second;
        last = it.first;
    }
    cout << ans << endl;
    return 0;
}

E-ペドラー 

トピック

最初の線n、mは、n個の点とm個のエッジを表します。

2行目のnaiは、その時点での金の価格を表しています。

次のm行はエッジを表し、各エッジは有向エッジです。ここで、xiはyiより小さくなければなりません。

今、彼は金を買うためにあるポイントを選び、次に金を売るために別のポイントに行き、最大の利益を求めなければなりません。

アイデア

答えはトポロジシーケンスで再帰的になります。dp[i]は、ソースポイント(そのポイントはわかりません)からポイントiまでの金の最も安い価格を表します。これは一方向のエッジであるため、これはポイントは絶対に戻りません。実行し、線形再帰を実行し、a [son] -dp [i]の最大値を更新するだけで、sonはiの子ノードです。

ACコード

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 2e5 + 5;
int dp[maxn], in[maxn], a[maxn];
vector<int> v[maxn];
queue<int> q;
int main(){
    int n, m;
    cin >> n >> m;
    for(int i = 1; i <= n; i ++) cin >> a[i];
    while(m --){
        int x, y;
        cin >> x >> y;
        v[x].push_back(y);
        in[y] ++;
    }
    for(int i = 1; i <= n; i ++){
        if(in[i] == 0) q.push(i);
        dp[i] = a[i]; //刚开始只初始化入度为0的节点然后wa了7个点,原因是存在2 3, 1 3种情况,也就是说这个图有可能是发散的,必须在跑到他之前就要初始化
    }
    int ans = -0x3f3f3f3f;
    while(q.size()){
        int t = q.front(); q.pop();
        for(auto it : v[t]){
            if(ans == -0x3f3f3f3f || ans < a[it] - dp[t]) ans = a[it] - dp[t];
            dp[it] = min(dp[it], dp[t]);
            if(--in[it] == 0) q.push(it);
        }
    }
    cout << ans << endl;
    return 0;
}

F- + 1-1x2

トピック

2つの数値x、yを指定します。各数値に対して、毎回+ 1、-1、または* 2を実行し、少なくともxをyに変更するために必要な操作の数を尋ねます。

アイデア

メモリ検索、dfs(y)は、xをyに変更するために必要なステップ数を表します

特にコードを参照してください

ACコード

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 2e5 + 5;
map<ll, ll> dp; //dp[y]表示将x变成y需要的步数
ll x, y;
ll dfs(ll yy){
    if(yy <= x) return x - yy; //如果x大于等于yy,那么x只能进行x-yy次 减操作到达yy
    if(dp.count(y)) return dp[yy]; //记忆化操作直接返回
    ll res = yy - x; //表示x进行yy-x次 加操作到达y
    if(yy % 2 == 0) res = min(res, dfs(yy / 2) + 1); //如果yy是偶数,那么就存在乘2的操作,使得x到达yy
    else res = min(res, 1 + min(dfs(yy + 1), dfs(yy - 1))); //不然就看看加1减1操作使得x到达yy,取一个最小值
    return dp[yy] = res; //记忆化存
}
int main(){
    cin >> x >> y;
    cout << dfs(y);
    return 0;
}

 

おすすめ

転載: blog.csdn.net/weixin_43911947/article/details/112447322