562 字
1 分钟
Atcoder_Beginner_Contest_461(A~D题)

题目链接:https://atcoder.jp/contests/abc461/tasks
A - Armor
按照题意判断输出即可。
#include <bits/stdc++.h>
using namespace std;using ll = long long;#define endl '\n'#define mod 998244353typedef pair<ll, ll> pll;typedef pair<int, int> pii;
void solved(){ int a, d; cin >> a >> d; if(a > d) cout << "No" << endl; else cout << "Yes" << endl;}
int main() { ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr); int _ = 1; // cin >> _; while(_--){ solved(); } return 0;}B - The Honest Woodcutters
我们判断每个伐木工拥有的斧头是否是他自己的(是否等于)即可,如果有一个不是那就输出,否则就。
#include <bits/stdc++.h>
using namespace std;using ll = long long;#define endl '\n'#define mod 998244353typedef pair<ll, ll> pll;typedef pair<int, int> pii;int a[110];int b[110];
void solved(){ int n; cin >> n; for(int i = 1; i <= n;i++) cin >> a[i]; for(int i = 1; i <= n;i++) cin >> b[i]; for(int i = 1; i <= n;i++){ if(b[a[i]] != i){ cout << "No" << endl; return; } } cout << "Yes" << endl;}
int main() { ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr); int _ = 1; // cin >> _; while(_--){ solved(); } return 0;}C - Variety
这里的思路是将每个颜色宝石中价值最大的放入数组,然后取最大的个计入总价值,也就是满足了个颜色种类这个条件。然后里面没选到的元素就放入。和其他宝石一起排序,然后再取价值最大的 - 个宝石取够个宝石计入总价值即可。
#include <bits/stdc++.h>
using namespace std;using ll = long long;#define endl '\n'#define mod 998244353typedef pair<ll, ll> pll;typedef pair<int, int> pii;
map<ll, vector<ll>> mp;vector<ll> max_vals;vector<ll> other_vals;
void solved(){ int n, k, m; cin >> n >> k >> m; for(int i = 1; i <= n;i++){ ll c, v; cin >> c >> v; mp[c].push_back(v); //用二维数组计入对应颜色c含有的所有价值v } //将map中的数组元素从大到小排序 for(auto &c : mp){ sort(c.second.begin(), c.second.end(), greater<ll>()); } for(auto it1 : mp){ ll cnt = 1; for(auto it2 : it1.second){ if(cnt){max_vals.push_back(it2),cnt--;continue;} //max_vals只取每个颜色的第一个 other_vals.push_back(it2); //其他就加入other_vals } } //排序之后取前m个 sort(max_vals.begin(), max_vals.end(), greater<ll>());
ll cnt = 0; ll ans = 0; for(auto it : max_vals){ if(cnt < m){ ans += it; cnt++; } else other_vals.push_back(it); } //排序之后取前k - m个 sort(other_vals.begin(), other_vals.end(), greater<ll>());
for(auto it : other_vals){ if(cnt != k){ ans += it; cnt++; } } cout << ans << endl;}
int main() { ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr); int _ = 1; // cin >> _; while(_--){ solved(); } return 0;}D - Count Subgrid Sum = K
这题直接暴力的复杂度会达到,没办法通过这题。思路是通过给定确定的矩阵上界和下界,然后再在上下界里取左右边界,然后统计矩阵内计数之和为的个数即为答案。这个原理的复杂度大概为,足够通过本题。
这里上下界的循环仍然有的复杂度,优化的地方是在给定上下界的每一列中计算整一列的整数之和,然后将个列压成了一维数组,求连续子序列之和为的数量有多少个。这里的解法是利用前缀和变式。我们知道时就是满足条件的区间。我们不妨改变一下式子。变成,也就是说,对于目前遍历到的前缀和,满足条件的区间的数量就是的出现频率。所以每次遍历时我们累加对应的即可。不过这里要注意要设置成,以正确统计区间左端点为的区间。(这里的数组是的)
这里的是为了记录每一次给定上下界的循环内使用到的,然后一一对应清零,供下一次循环使用。(如果使用直接将全部覆写为的话需要写入次,可能超时,所以只把用到清零即可)
#include <bits/stdc++.h>
using namespace std;using ll = long long;#define endl '\n'#define mod 998244353typedef pair<ll, ll> pll;typedef pair<int, int> pii;
vector<string> grid;vector<int> column, prefixL_cnt, touched;
void solved(){ int h, w, k; ll ans = 0; cin >> h >> w >> k; grid.resize(h + 1); column.resize(w + 1); prefixL_cnt.resize(h * w + 10);
for(int i = 1; i <= h;i++){ cin >> grid[i]; grid[i] = " " + grid[i]; }
//上界 for(int i = 1; i <= h;i++){ //清空column fill(column.begin(), column.end(), 0);
//下界 for (int j = i; j <= h;j++){ //压缩为一维数组 for(int l = 1; l <= w;l++){ column[l] += grid[j][l] - '0'; } //当前的前缀和 int prefix = 0; prefixL_cnt[0] = 1; touched.push_back(0);
for(int i = 1; i <= w;i++){ prefix += column[i]; if(prefix >= k) ans += prefixL_cnt[prefix - k]; //统计满足条件的区间 if(prefixL_cnt[prefix] == 0) touched.push_back(prefix); //第一次出现时计入touched中 prefixL_cnt[prefix]++; } //只清空用过的prefixL_cnt[x] for(int x : touched){ prefixL_cnt[x] = 0; } touched.clear(); } } cout << ans << endl;}
int main() { ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr); int _ = 1; // cin >> _; while(_--){ solved(); } return 0;}Atcoder_Beginner_Contest_461(A~D题)
https://mkrari.cn/posts/abc_461/