AtCoder Beginner Contest 298 题解
Posted RB16B
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AtCoder Beginner Contest 298 题解相关的知识,希望对你有一定的参考价值。
题面:https://atcoder.jp/contests/abc298/tasks_print
A - Job Interview
直接模拟即可。
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif
typedef long long ll;
typedef pair < int, int > PII;
typedef int itn;
mt19937 RND_MAKER (chrono :: steady_clock :: now ().time_since_epoch ().count ());
inline ll randomly (const ll l, const ll r) return (RND_MAKER () ^ (1ull << 63)) % (r - l + 1) + l;
//#define int long long
const double pi = acos (-1);
//__gnu_pbds :: tree < Key, Mapped, Cmp_Fn = std :: less < Key >, Tag = rb_tree_tag, Node_Upadte = null_tree_node_update, Allocator = std :: allocator < char > > ;
//__gnu_pbds :: tree < PPS, __gnu_pbds :: null_type, less < PPS >, __gnu_pbds :: rb_tree_tag, __gnu_pbds :: tree_order_statistics_node_update > tr;
inline int read ()
int x = 0, f = 0;
char c = getchar ();
for ( ; c < \'0\' || c > \'9\' ; c = getchar ()) f |= (c == \'-\');
for ( ; c >= \'0\' && c <= \'9\' ; c = getchar ()) x = (x << 1) + (x << 3) + (c & 15);
return !f ? x : -x;
int n, o, x;
char s[105];
signed main ()
n = read ();
scanf ("%s", s + 1);
for (int i = 1;i <= n; ++ i)
o += (s[i] == \'o\');
x += (s[i] == \'x\');
if (o > 0 && x == 0) printf ("Yes\\n");
else printf ("No\\n");
return 0;
B - Coloring Matrix
因为旋转 \\(4\\) 次后就会变成原样,所以只需要模拟十次甚至九次即可。
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif
typedef long long ll;
typedef pair < int, int > PII;
typedef int itn;
mt19937 RND_MAKER (chrono :: steady_clock :: now ().time_since_epoch ().count ());
inline ll randomly (const ll l, const ll r) return (RND_MAKER () ^ (1ull << 63)) % (r - l + 1) + l;
//#define int long long
const double pi = acos (-1);
//__gnu_pbds :: tree < Key, Mapped, Cmp_Fn = std :: less < Key >, Tag = rb_tree_tag, Node_Upadte = null_tree_node_update, Allocator = std :: allocator < char > > ;
//__gnu_pbds :: tree < PPS, __gnu_pbds :: null_type, less < PPS >, __gnu_pbds :: rb_tree_tag, __gnu_pbds :: tree_order_statistics_node_update > tr;
inline int read ()
int x = 0, f = 0;
char c = getchar ();
for ( ; c < \'0\' || c > \'9\' ; c = getchar ()) f |= (c == \'-\');
for ( ; c >= \'0\' && c <= \'9\' ; c = getchar ()) x = (x << 1) + (x << 3) + (c & 15);
return !f ? x : -x;
int a[105][105], b[105][105], c[105][105], n;
inline void rotate ()
for (int i = 1;i <= n; ++ i)
for (int j = 1;j <= n; ++ j)
c[n - j + 1][i] = a[i][j];
for (int i = 1;i <= n; ++ i)
for (int j = 1;j <= n; ++ j)
a[i][j] = c[i][j];
inline bool check ()
for (int i = 1;i <= n; ++ i)
for (int j = 1;j <= n; ++ j)
if (b[i][j] == 0 && a[i][j] == 1) return false;
return true;
signed main ()
n = read ();
for (int i = 1;i <= n; ++ i)
for (int j = 1;j <= n; ++ j)
a[i][j] = read ();
for (int i = 1;i <= n; ++ i)
for (int j = 1;j <= n; ++ j)
b[i][j] = read ();
for (int i = 0;i < 10; ++ i)
if (check ())
printf ("Yes\\n");
return 0;
rotate ();
printf ("No\\n");
return 0;
C - Cards Query Problem
每个盒子可以用 std :: priority_queue
维护,每张卡片因为要去重就用 std :: set
维护即可。
有点坑,如果不用 set 去重的话就会 TLE。
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif
typedef long long ll;
typedef pair < int, int > PII;
typedef int itn;
mt19937 RND_MAKER (chrono :: steady_clock :: now ().time_since_epoch ().count ());
inline ll randomly (const ll l, const ll r) return (RND_MAKER () ^ (1ull << 63)) % (r - l + 1) + l;
//#define int long long
const double pi = acos (-1);
//__gnu_pbds :: tree < Key, Mapped, Cmp_Fn = std :: less < Key >, Tag = rb_tree_tag, Node_Upadte = null_tree_node_update, Allocator = std :: allocator < char > > ;
//__gnu_pbds :: tree < PPS, __gnu_pbds :: null_type, less < PPS >, __gnu_pbds :: rb_tree_tag, __gnu_pbds :: tree_order_statistics_node_update > tr;
inline int read ()
int x = 0, f = 0;
char c = getchar ();
for ( ; c < \'0\' || c > \'9\' ; c = getchar ()) f |= (c == \'-\');
for ( ; c >= \'0\' && c <= \'9\' ; c = getchar ()) x = (x << 1) + (x << 3) + (c & 15);
return !f ? x : -x;
priority_queue < int, vector < int >, greater < int > > box[200005];
set < int > card[200005];
inline void th2 (priority_queue < int, vector < int >, greater < int > > qwq)
priority_queue < int, vector < int >, greater < int > > tmp = qwq;
while (!tmp.empty ())
int x = tmp.top ();
printf ("%d ", x);
tmp.pop ();
printf ("\\n");
inline void th3 (int xd)
vector < int > need;
need.clear ();
for (auto x : card[xd]) need.push_back (x);
sort (need.begin (), need.end ());
for (auto x : need) printf ("%d ", x);
printf ("\\n");
signed main ()
int n = read (), q = read ();
while (q --)
int op = read ();
if (op == 1)
int x = read (), y = read ();
if (card[x].find (y) == card[x].end ()) card[x].insert (y);
box[y].push (x);
else if (op == 2)
int x = read ();
th2 (box[x]);
else
int x = read ();
th3 (x);
return 0;
D - Writing a Numeral
数学题一道。
我们将数的每一位用 vector 维护,模 \\(998244353\\) 的值用一个变量 \\(S\\) 维护,用一个指针指向 vector 的表头。
操作 1:\\(10S + x \\to S\\),vector 后面插入 \\(x\\)。
操作 2:设 vector 的表头为 \\(x\\),取出之后将指针右移一位,并前去最高位对应的值即可。
操作 3:无脑输出。
感觉就是水题一道,关键在于取模之后还要进行特殊的处理(x = (x % mod + mod) % mod;
),某人(不是我)因为这个 WA 了。
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif
typedef long long ll;
typedef pair < int, int > PII;
typedef int itn;
mt19937 RND_MAKER (chrono :: steady_clock :: now ().time_since_epoch ().count ());
inline ll randomly (const ll l, const ll r) return (RND_MAKER () ^ (1ull << 63)) % (r - l + 1) + l;
#define int long long
const double pi = acos (-1);
//__gnu_pbds :: tree < Key, Mapped, Cmp_Fn = std :: less < Key >, Tag = rb_tree_tag, Node_Upadte = null_tree_node_update, Allocator = std :: allocator < char > > ;
//__gnu_pbds :: tree < PPS, __gnu_pbds :: null_type, less < PPS >, __gnu_pbds :: rb_tree_tag, __gnu_pbds :: tree_order_statistics_node_update > tr;
inline int read ()
int x = 0, f = 0;
char c = getchar ();
for ( ; c < \'0\' || c > \'9\' ; c = getchar ()) f |= (c == \'-\');
for ( ; c >= \'0\' && c <= \'9\' ; c = getchar ()) x = (x << 1) + (x << 3) + (c & 15);
return !f ? x : -x;
inline int ksm (int a, int b, int p)
int res = 1;
while (b)
if (b & 1) res = res * a % p;
b >>= 1;
a = a * a % p;
return res;
const int mod = 998244353;
int cur = 1, i10, q, pw10[600010], siz, head = 0;
vector < int > ary;
signed main ()
pw10[0] = 1;
for (int i = 1;i <= 6e5 + 5; ++ i) pw10[i] = pw10[i - 1] * 10 % mod;
ary.push_back (1); siz = 1;
i10 = ksm (10, mod - 2, mod);
q = read ();
while (q --)
int op = read ();
if (op == 1)
int x = read ();
ary.push_back (x);
cur = (cur * 10 + x) % mod;
siz ++;
else if (op == 2)
int x = ary[head];
head ++;
siz --;
cur -= x * pw10[siz] % mod;
cur = (cur % mod + mod) % mod;
else
printf ("%lld\\n", cur);
return 0;
E - Unfair Sugoroku
比较裸的一道概率 dp。
设 \\(f_A,B,0/1\\) 为当前 Ta. 在 \\(A\\),Ao. 在 \\(B\\),\\(0\\) 表示该 Ta. 走,\\(1\\) 表示该 Ao. 走,Ta. 胜利的概率。
然后枚举 Ta. / Ao. 掷出的值,直接按概率 dp 转移即可。
边界条件:\\(f_N,x,0=f_N,x,1=1,f_x,N,0=f_x,N,1=0(1 \\leq x < N)\\)。
感觉这道题还是比较容易想,一遍就过了样例,一遍就 AC 了,还是比较的经典的。
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif
typedef long long ll;
typedef pair < int, int > PII;
typedef int itn;
mt19937 RND_MAKER (chrono :: steady_clock :: now ().time_since_epoch ().count ());
inline ll randomly (const ll l, const ll r) return (RND_MAKER () ^ (1ull << 63)) % (r - l + 1) + l;
#define int long long
const double pi = acos (-1);
//__gnu_pbds :: tree < Key, Mapped, Cmp_Fn = std :: less < Key >, Tag = rb_tree_tag, Node_Upadte = null_tree_node_update, Allocator = std :: allocator < char > > ;
//__gnu_pbds :: tree < PPS, __gnu_pbds :: null_type, less < PPS >, __gnu_pbds :: rb_tree_tag, __gnu_pbds :: tree_order_statistics_node_update > tr;
inline int read ()
int x = 0, f = 0;
char c = getchar ();
for ( ; c < \'0\' || c > \'9\' ; c = getchar ()) f |= (c == \'-\');
for ( ; c >= \'0\' && c <= \'9\' ; c = getchar ()) x = (x << 1) + (x << 3) + (c & 15);
return !f ? x : -x;
const int mod = 998244353;
inline int ksm (int a, int b, int p)
int res = 1;
while (b)
if (b & 1) res = res * a % p;
b >>= 1;
a = a * a % p;
return res;
int f[105][105][2], g[105][105][2], n, a, b, p, q, ip, iq;
inline int dfs (int A, int B, int type)
if (g[A][B][type]) return f[A][B][type];
g[A][B][type] = 1;
if (type == 0)
int ans = 0;
for (int i = 1;i <= p; ++ i)
int goal = min (A + i, n);
ans = (ans + dfs (goal, B, type ^ 1) * ip % mod) % mod;
return f[A][B][type] = ans;
else
int ans = 0;
for (int i = 1;i <= q; ++ i)
int goal = min (B + i, n);
ans = (ans + dfs (A, goal, type ^ 1) * iq % mod) % mod;
return f[A][B][type] = ans;
signed main ()
n = read (), a = read (), b = read (), p = read (), q = read ();
ip = ksm (p, mod - 2, mod), iq = ksm (q, mod - 2, mod);
for (int i = 1;i < n; ++ i)
f[n][i][0] = 1, g[n][i][0] = 1;
f[i][n][0] = 0, g[n][i][0] = 1;
f[n][i][1] = 1, g[n][i][1] = 1;
f[i][n][1] = 0, g[n][i][1] = 1;
printf ("%lld\\n", dfs (a, b, 0));
return 0;
F - Rook Score
枚举所有有点的列(\\((R,C)\\) 就选自这一列),用一个线段树维护所有有点的行的权值之和,只需要在计算每行的答案的时候减掉这一行对应的点的权值即可。
这道题感觉不难想,就是代码难写了一点(可能是我的思路问题),赛时因为数组开小了 2 倍 WA 了一发。
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif
typedef long long ll;
typedef pair < int, int > PII;
typedef int itn;
mt19937 RND_MAKER (chrono :: steady_clock :: now ().time_since_epoch ().count ());
inline ll randomly (const ll l, const ll r) return (RND_MAKER () ^ (1ull << 63)) % (r - l + 1) + l;
#define int long long
const double pi = acos (-1);
//__gnu_pbds :: tree < Key, Mapped, Cmp_Fn = std :: less < Key >, Tag = rb_tree_tag, Node_Upadte = null_tree_node_update, Allocator = std :: allocator < char > > ;
//__gnu_pbds :: tree < PPS, __gnu_pbds :: null_type, less < PPS >, __gnu_pbds :: rb_tree_tag, __gnu_pbds :: tree_order_statistics_node_update > tr;
inline int read ()
int x = 0, f = 0;
char c = getchar ();
for ( ; c < \'0\' || c > \'9\' ; c = getchar ()) f |= (c == \'-\');
for ( ; c >= \'0\' && c <= \'9\' ; c = getchar ()) x = (x << 1) + (x << 3) + (c & 15);
return !f ? x : -x;
int n, rc[400005], r[200005], c[200005], w[200005];
int mx[1600005], inc[1600005];
inline void push_up (int u) mx[u] = max (mx[u << 1], mx[u << 1 | 1]);
inline void push_down (int u)
if (inc[u] == 0) return ;
inc[u << 1] += inc[u], inc[u << 1 | 1] += inc[u];
mx[u << 1] += inc[u], mx[u << 1 | 1] += inc[u];
inc[u] = 0;
inline void build (int u, int l, int r)
inc[u] = 0;
if (l == r) return ;
int mid = l + r >> 1;
build (u << 1, l, mid), build (u << 1 | 1, mid + 1, r);
push_up (u);
inline void modify (int u, int l, int r, int x, int y, int v)
if (x <= l && r <= y)
mx[u] += v;
inc[u] += v;
return ;
push_down (u);
int mid = l + r >> 1;
if (x <= mid) modify (u << 1, l, mid, x, y, v);
if (y > mid) modify (u << 1 | 1, mid + 1, r, x, y, v);
push_up (u);
inline int query (int u, int l, int r, int x, int y)
if (x <= l && r <= y) return mx[u];
push_down (u);
int mid = l + r >> 1, ans = 0;
if (x <= mid) ans = max (ans, query (u << 1, l, mid, x, y));
if (y > mid) ans = max (ans, query (u << 1 | 1, mid + 1, r, x, y));
return ans;
map < int, int > mp;
int qwq[400005];
vector < int > R[400005], C[400005];
signed main ()
n = read ();
for (int i = 1;i <= n; ++ i)
r[i] = read (), c[i] = read (), w[i] = read ();
rc[i] = r[i], rc[i + n] = c[i];
sort (rc + 1, rc + 1 + 2 * n);
for (int i = 1;i <= 2 * n; ++ i)
if (rc[i] != rc[i - 1]) mp[rc[i]] = mp[rc[i - 1]] + 1;
int m = mp[rc[2 * n]];
build (1, 1, m);
for (int i = 1;i <= n; ++ i)
r[i] = mp[r[i]];
c[i] = mp[c[i]];
R[r[i]].push_back (i);
C[c[i]].push_back (i);
for (int i = 1;i <= n; ++ i)
qwq[r[i]] += w[i];
for (int i = 1;i <= m; ++ i) modify (1, 1, m, i, i, qwq[i]);
int ans = -9e18;
for (int i = 1;i <= m; ++ i)
int tot = 0;
for (int x : C[i]) modify (1, 1, m, r[x], r[x], -w[x]), tot += w[x];
ans = max (ans, tot + query (1, 1, m, 1, m));
for (int x : C[i]) modify (1, 1, m, r[x], r[x], w[x]);
printf ("%lld\\n", ans);
return 0;
G - Strawberry War
个人感觉这道题思维难度不算太大,但代码非常难写()。
首先要枚举一个值(一定要是某个子矩形的和)\\(x\\),表示分割成的每个子矩形的和的下限。
那么对于这个值(\\(x\\)),答案就是分割成的子矩形的和的最大值减去 \\(x\\)(如果 \\(x\\) 没有出现,那么 \\(x\\) 还可以更大)。
那么我们可以考虑进行 dp,设 \\(f_x,Lx,Rx,Ly,Ry\\) 表示对子矩形 \\(((Lx,Rx),(Ly,Ry))\\) 切了 \\(x\\) 刀后的最大值(当然也可以存减去 \\(x\\) 的值的最大值),那么就枚举一下切的位置,枚举一下切出来的两个子矩形内部各切了多少刀,两者取个 max 转移即可。
赛时就是想二分最小值,就做不出来了()。
可以发现最小值一定是某个子矩形的和,每次做一个 dp 就做出来了。
思想还是挺妙的,但是也不是特别难想,正确性显然()。
吐槽一下代码有点难写()。
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif
typedef long long ll;
typedef pair < int, int > PII;
typedef int itn;
mt19937 RND_MAKER (chrono :: steady_clock :: now ().time_since_epoch ().count ());
inline ll randomly (const ll l, const ll r) return (RND_MAKER () ^ (1ull << 63)) % (r - l + 1) + l;
#define int long long
const double pi = acos (-1);
//__gnu_pbds :: tree < Key, Mapped, Cmp_Fn = std :: less < Key >, Tag = rb_tree_tag, Node_Upadte = null_tree_node_update, Allocator = std :: allocator < char > > ;
//__gnu_pbds :: tree < PPS, __gnu_pbds :: null_type, less < PPS >, __gnu_pbds :: rb_tree_tag, __gnu_pbds :: tree_order_statistics_node_update > tr;
inline int read ()
int x = 0, f = 0;
char c = getchar ();
for ( ; c < \'0\' || c > \'9\' ; c = getchar ()) f |= (c == \'-\');
for ( ; c >= \'0\' && c <= \'9\' ; c = getchar ()) x = (x << 1) + (x << 3) + (c & 15);
return !f ? x : -x;
int a[7][7], sum[7][7][7][7], n, m, T, f[40][7][7][7][7];
inline int dp (int th)
for (int Li = 1;Li <= n; ++ Li)
for (int Ri = Li;Ri <= n; ++ Ri)
for (int Lj = 1;Lj <= m; ++ Lj)
for (int Rj = Lj;Rj <= m; ++ Rj)
for (int k = 0;k <= T; ++ k) f[k][Li][Ri][Lj][Rj] = 4e18;
if (sum[Li][Ri][Lj][Rj] >= th) f[0][Li][Ri][Lj][Rj] = sum[Li][Ri][Lj][Rj] - th;
for (int tm = 1;tm <= T; ++ tm)
for (int Li = 1;Li <= n; ++ Li)
for (int Ri = Li;Ri <= n; ++ Ri)
for (int Lj = 1;Lj <= m; ++ Lj)
for (int Rj = Lj;Rj <= m; ++ Rj)
for (int lf = tm - 1;lf >= 0; -- lf)
for (int cut = Li + 1;cut <= Ri; ++ cut)
int tmp = max (f[lf][Li][cut - 1][Lj][Rj], f[tm - lf - 1][cut][Ri][Lj][Rj]);
f[tm][Li][Ri][Lj][Rj] = min (f[tm][Li][Ri][Lj][Rj], tmp);
for (int cut = Lj + 1;cut <= Rj; ++ cut)
int tmp = max (f[lf][Li][Ri][Lj][cut - 1], f[tm - lf - 1][Li][Ri][cut][Rj]);
f[tm][Li][Ri][Lj][Rj] = min (f[tm][Li][Ri][Lj][Rj], tmp);
return f[T][1][n][1][m];
signed main ()
n = read (), m = read (), T = read ();
for (int i = 1;i <= n; ++ i)
for (int j = 1;j <= m; ++ j)
a[i][j] = read ();
for (int Li = 1;Li <= n; ++ Li)
for (int Ri = Li;Ri <= n; ++ Ri)
for (int Lj = 1;Lj <= m; ++ Lj)
for (int Rj = Lj;Rj <= m; ++ Rj)
for (int i = Li;i <= Ri; ++ i)
for (int j = Lj;j <= Rj; ++ j)
sum[Li][Ri][Lj][Rj] += a[i][j];
int ans = 9e18;
for (int Li = 1;Li <= n; ++ Li)
for (int Ri = Li;Ri <= n; ++ Ri)
for (int Lj = 1;Lj <= m; ++ Lj)
for (int Rj = Lj;Rj <= m; ++ Rj)
int base = sum[Li][Ri][Lj][Rj];
ans = min (ans, dp (base));
printf ("%lld\\n", ans);
return 0;
Atcoder Beginner Contest 251 D——题解
以上是关于AtCoder Beginner Contest 298 题解的主要内容,如果未能解决你的问题,请参考以下文章
AtCoder Beginner Contest 115 题解