AtCoder Beginner Contest 188 Problem Solving Report

Title link: https://atcoder.jp/contests/abc188/tasks

A - Three-Point Shot

Topic

Give you x, y and ask you whether the smaller value plus 3 can exceed the larger value

Ideas

Direct judgment

ac code

#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 - Orthogonality

Topic

Two arrays, the corresponding positions are multiplied and summed to see if it is equal to 0

Ideas

Direct simulation

ac code

#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 Tournament

Topic

Give you an n, and then 2^n numbers, representing the score of the i-th person. Each round has two pk adjacent to each other. The one with the higher score wins the next round and outputs the initial subscript of the final runner-up.

Ideas

vector simulation

ac code

#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 - Snuke Prime

Topic

Takahashi went out to play, and now provides n items, the time is [ai, bi], these items need to spend ci each day, but it can choose to spend C yuan a day to play all the items that appear on this day, he must Play, ask him to spend the least

For example, in the first example, there are 2 items, it costs 6 to play all the items that appear in one day, the first item appears in [1,2], it costs 4 per day, and the second item appears in [2,2], it costs per day 4. That means it costs 4 on the first day and 4 + 4=8 on the second day, but 8<6 can choose to spend 6 yuan to play item 1, 2, so a total of 4+6=10

Ideas

The difference is to calculate the cost of each item on the day, and then the daily cost is the smaller value of the current day’s cost and C

ac code

#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 - Peddler 

Topic

The first line n, m represents n points and m edges,

The n ai in the second line represent the price of gold at that point,

The next m rows represent edges, each edge is a directed edge, where xi must be less than yi

Now he has to choose one point to buy gold, and then go to another point to sell gold, seeking maximum profit.

Ideas

The answer is recursively in the topological sequence, dp[i] represents the cheapest price of gold that goes from the source point (I don’t know that point) to the point i. Because it is a one-way edge, then this point will definitely not go back. Only run down, then linear recursion, and then only need to update the maximum value of a[son]-dp[i], son is a child node of i

ac code

#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

Topic

Give you two numbers x, y, you can perform +1 or -1 or *2 on each number each time, and ask you at least how many operations you need to change x to y

Ideas

Memory search, dfs(y) represents the number of steps required to change x to y

See the code specifically

ac code

#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;
}

 

Guess you like

Origin blog.csdn.net/weixin_43911947/article/details/112447322