Lien titre: https://atcoder.jp/contests/abc188/tasks
A - Prise de vue en trois points
Sujet
Donnez-vous x, y et demandez-vous si la plus petite valeur plus 3 peut dépasser la plus grande valeur
Idées
Jugement direct
code 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 - Orthogonalité
Sujet
Deux tableaux, les positions correspondantes sont multipliées et additionnées pour voir si elle est égale à 0
Idées
Simulation directe
code 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 - Tournoi ABC
Sujet
Donnez-vous un n, puis 2 ^ n nombres, qui représentent le score de la i-ème personne. Chaque tour a deux pk adjacents l'un à l'autre. Celui avec le score le plus élevé l'emporte, entre dans le tour suivant et sort le premier indice du finaliste final
Idées
simulation vectorielle
code 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 - Snuke Prime
Sujet
Takahashi est sorti pour jouer et fournit maintenant n objets, le temps est [ai, bi], ces objets doivent dépenser ci chaque jour, mais il peut choisir de dépenser C yuan par jour pour jouer à tous les objets qui apparaissent ce jour-là , il doit jouer, lui demander de dépenser le moins
Par exemple, dans le premier exemple, il y a 2 éléments, il en coûte 6 pour lire tous les éléments qui apparaissent dans une journée, le premier élément apparaît dans [1,2], il en coûte 4 par jour et le deuxième élément apparaît dans [2,2], cela coûte par jour 4, ce qui signifie que le premier jour doit dépenser 4, le lendemain doit dépenser 4 + 4 = 8, mais 8 <6 peuvent choisir de dépenser 6 yuans pour jouer au projet 1, 2, donc un total de 4 + 6 = 10
Idées
La différence consiste à calculer le coût de chaque article le jour, puis le coût quotidien correspond à la valeur la plus petite du coût du jour en cours et C
code 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 - Colporteur
Sujet
La première ligne n, m représente n points et m arêtes,
Le n ai dans la deuxième ligne représente le prix de l'or à ce point,
Les m lignes suivantes représentent les arêtes, chaque arête est une arête dirigée, où xi doit être inférieur à yi
Maintenant, il doit choisir un point pour acheter de l'or, puis passer à un autre pour vendre de l'or, en cherchant un profit maximum.
Idées
La réponse est récursive dans la séquence topologique, dp [i] représente le prix de l'or le moins cher qui va du point source (je ne sais pas ce point) au point i. Parce que c'est une arête à sens unique, alors ceci point ne reviendra certainement pas. Seulement descente, puis récursion linéaire, et ensuite seulement besoin de mettre à jour la valeur maximale de a [son] -dp [i], son est un nœud enfant de i
code 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
Sujet
Donnez-vous deux nombres x, y, vous pouvez effectuer +1 ou -1 ou * 2 sur chaque nombre à chaque fois, et vous demander au moins combien d'opérations vous devez changer x en y
Idées
Recherche de mémoire, dfs (y) représente le nombre d'étapes nécessaires pour changer x en y
Voir le code spécifiquement
code 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;
}