Codeforces Round #742 (Div. 2) 题解
Posted 人形自走Bug生成器
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #742 (Div. 2) 题解相关的知识,希望对你有一定的参考价值。
旅行传送门
A. Domino Disaster
题意:有一个被大小为 \\(1*2\\) 的多米诺骨牌覆盖了的 \\(2\\) 行 \\(n\\) 列的网格。 骨牌可以垂直或水平放置,告诉你其中一排网格,问另一排网格是何样?
题目分析:模拟即可。
AC代码:
#include <bits/stdc++.h>
#define rep(i, x, y) for (register int i = (x); i <= (y); i++)
#define down(i, x, y) for (register int i = (x); i >= (y); i--)
using namespace std;
void solve()
{
int n;
cin >> n;
string s, t;
cin >> s;
rep(i, 0, n - 1)
{
switch (s[i])
{
case \'U\':
t += \'D\';
break;
case \'D\':
t += \'U\';
break;
case \'L\':
t += \'L\';
break;
case \'R\':
t += \'R\';
break;
default:
break;
}
}
cout << t << endl;
}
int main(int argc, char const *argv[])
{
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin >> t;
while (t--)
solve();
return 0;
}
B. MEXor Mixup
题意:给你两个数 \\(a\\) , \\(b\\) ,其中 \\(a\\) 是数组中最小的未出现的非负整数, \\(b\\) 是整个数组的异或和,问满足条件的数组的最小长度是多少。
题目分析:首先可以明确的是所求 \\(ans \\geq a\\) ,不妨设 \\(c\\) 为 \\(0\\) ~ \\(a-1\\) 的异或和,接下来分三种情况讨论即可:
-
\\(c = b\\) ,此时 \\(ans = a\\)
-
\\(c \\not= b\\) 且 \\(c \\bigoplus b \\not= a\\) ,此时 \\(ans = a+1\\)
-
\\(c \\not= b\\) 且 \\(c \\bigoplus b = a\\) ,此时 \\(ans = a+2\\)
这里解释一下,由于 \\(b\\) 是整个数组的异或和, 现在我们要让 \\(c\\) 异或上某个值 \\(d\\) 得到 \\(b\\) ,如果 \\(d\\) 不是 \\(a\\) 的话,我们直接把 \\(d\\) 添加进数组就好,否则的话就要用另外两个值异或起来得到 \\(a\\) 再去和 \\(c\\) 异或得到 \\(b\\) ,因为 \\(a\\) 不能出现在数组中,这种情况下就是 \\(ans = a+2\\) 。
有个异或和的小性质: \\(i\\) 从 \\(0\\) 开始算起, 有 \\(i \\bigoplus i+1 = 1\\) 。
AC代码:
#include <bits/stdc++.h>
#define rep(i, x, y) for (register int i = (x); i <= (y); i++)
#define down(i, x, y) for (register int i = (x); i >= (y); i--)
const int maxn = 3e5 + 5;
char buf[1 << 23], *p1 = buf, *p2 = buf, obuf[1 << 23], *O = obuf;
#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
inline int read()
{
int x = 0, f = 1;
char ch = getchar();
while (!isdigit(ch))
{
if (ch == \'-\')
f = -1;
ch = getchar();
}
while (isdigit(ch))
{
x = x * 10 + ch - \'0\';
ch = getchar();
}
return x * f;
}
int main(int argc, char const *argv[])
{
int T = read();
std ::vector<int> c(maxn);
rep(i, 1, 300000) c[i] = c[i - 1] ^ i;
while (T--)
{
int a = read(), b = read();
if (c[a - 1] == b)
printf("%d\\n", a);
else if (c[a - 1] ^ b ^ a)
printf("%d\\n", a + 1);
else
printf("%d\\n", a + 2);
}
return 0;
}
// int check(int a)
// {
// switch (a % 4)
// {
// case 0:
// return 0;
// case 1:
// return a - 1;
// case 2:
// return 1;
// case 3:
// return (a - 1) ^ 1;
// }
// }
// int main(int argc, char const *argv[])
// {
// int T = read();
// while (T--)
// {
// int a = read(), b = read();
// int c = check(a);
// if (c == b)
// printf("%d\\n", a);
// else if (c ^ b ^ a)
// printf("%d\\n", a + 1);
// else
// printf("%d\\n", a + 2);
// }
// return 0;
// }
C. Carrying Conundrum
题意:定义新的加法运算:计算时所有的进位都要左移一位。
给你一个数 \\(n\\) ,问有多少对 \\((a,b)\\) 在新定义下满足 \\(a + b = n\\) ( \\((a,b)\\) 和 \\((b,a)\\) 算作不同方案)?
题目分析:平时的加法运算进位规则是个位进十位、十位进百位、百位进千位……每一位的进位都对它的后一位有贡献,密不可分。但在新定义下,贡献关系变为奇数位只对奇数位有贡献,偶数位只对偶数位有贡献,因此我们扫描整个 \\(n\\) ,将奇偶数位的数分别抽出来,称为 \\(odd\\) 、 \\(even\\) ,一个数 \\(x\\) 可以由 \\((0,x)\\) 、 \\((1,x-1)\\) 、 \\((2,x-2)\\) …… \\((x-1,1)\\) 、 \\((x,0)\\) 共 \\(x+1\\) 种方案组成,所以答案即为 \\((odd+1)*(even+1)\\) ,但我们还要减去 \\(2\\) ,因为 \\((a,b)\\) 为正整数对。因此,答案是 \\((odd+1)*(even+1)-2\\) 。
举个栗子:\\(2021\\) , 奇数位与偶数位组成的数字分别为 \\(22\\) 和 \\(01\\) , \\(22\\) 的组成方式有 \\(23\\) 种, \\(1\\) 的话有 \\(2\\) 种,但 \\((0,2021)\\) 与 \\((2021,0)\\) 不符合题意,所以答案为 \\(23*2-2=44\\) 种。
AC代码:
#include <bits/stdc++.h>
#define rep(i, x, y) for (register int i = (x); i <= (y); i++)
#define down(i, x, y) for (register int i = (x); i >= (y); i--)
using namespace std;
int main(int argc, char const *argv[])
{
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin >> T;
while (T--)
{
string s, odd, even;
cin >> s;
int len = s.length() - 1;
rep(i, 0, len) if (i & 1) even += s[i];
else odd += s[i];
if (even.empty())
{
printf("%lld\\n", stoi(odd) - 1);
continue;
}
int a = stoi(odd), b = stoi(even);
printf("%lld\\n", 1ll * (a + 1) * (b + 1) - 2);
}
return 0;
}
D. Expression Evaluation Error
题意:给你一个十进制的数 \\(s\\) ,要将其拆成 \\(n\\) 个十进制数 ,使得这 \\(n\\) 个十进制数在十一进制的表示下总和最大,求任一拆分方案。
题目分析:明早补。
AC代码:
#include <bits/stdc++.h>
char buf[1 << 23], *p1 = buf, *p2 = buf, obuf[1 << 23], *O = obuf;
#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
inline int read()
{
int x = 0, f = 1;
char ch = getchar();
while (!isdigit(ch))
{
if (ch == \'-\')
f = -1;
ch = getchar();
}
while (isdigit(ch))
{
x = x * 10 + ch - \'0\';
ch = getchar();
}
return x * f;
}
int main(int argc, char const *argv[])
{
int t = read();
while (t--)
{
int s = read(), n = read();
int d = (int)log10(s);
int p = pow(10, d);
for (int i = n; i > 1; --i)
{
while (s - p < i - 1)
p /= 10;
printf("%d ", p);
s -= p;
}
printf("%d\\n", s);
}
return 0;
}
E. Non-Decreasing Dilemma
题意:已知一个数列,你需要进行下面两种操作:
-
将 \\(a_x\\) 的值修改为 \\(y\\)
-
求出某区间非递减子序列的个数
题目分析:线段树,明早补。
AC代码:
#include <bits/stdc++.h>
#define rep(i, x, y) for (register int i = (x); i <= (y); i++)
#define down(i, x, y) for (register int i = (x); i >= (y); i--)
using ll = long long;
const int maxn = 2e5 + 5;
char buf[1 << 23], *p1 = buf, *p2 = buf, obuf[1 << 23], *O = obuf;
#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
inline ll read()
{
ll x = 0, f = 1;
char ch = getchar();
while (!isdigit(ch))
{
if (ch == \'-\')
f = -1;
ch = getchar();
}
while (isdigit(ch))
{
x = x * 10 + ch - \'0\';
ch = getchar();
}
return x * f;
}
std::vector<ll> a(maxn);
struct node
{
ll sum, lv, rv, mxl, mxr, len, flag;
} tree[maxn << 2];
node merge(node x, node y)
{
node res;
res.sum = x.sum + y.sum;
res.lv = x.lv, res.rv = y.rv;
res.len = x.len + y.len;
res.flag = 0;
if (x.rv <= y.lv)
res.sum += x.mxr * y.mxl;
if (x.flag && x.rv <= y.lv)
res.mxl = x.len + y.mxl;
else
res.mxl = x.mxl;
if (y.flag && x.rv <= y.lv)
res.mxr = x.mxr + y.len;
else
res.mxr = y.mxr;
if (x.flag && y.flag && x.rv <= y.lv)
res.flag = 1;
return res;
}
#define lson (k << 1)
#define rson (k << 1 | 1)
void build(ll k, ll l, ll r)
{
if (l == r)
{
tree[k].lv = tree[k].rv = a[l];
tree[k].sum = tree[k].mxl = tree[k].mxr = tree[k].len = tree[k].flag = 1;
return;
}
ll mid = (l + r) >> 1;
build(lson, l, mid);
build(rson, mid + 1, r);
tree[k] = merge(tree[lson], tree[rson]);
}
void update(ll k, ll l, ll r, ll x, ll y)
{
if (l == r && l == x)
{
tree[k].lv = tree[k].rv = y;
return;
}
ll mid = (l + r) >> 1;
x <= mid ? update(lson, l, mid, x, y) : update(rson, mid + 1, r, x, y);
tree[k] = merge(tree[lson], tree[rson]);
}
node query(ll k, ll l, ll r, ll ql, ll qr)
{
if (l >= ql && r <= qr)
return tree[k];
ll mid = (l + r) >> 1;
if (qr <= mid)
return query(lson, l, mid, ql, qr);
else if (ql > mid)
return query(rson, mid + 1, r, ql, qr);
else
return merge(query(lson, l, mid, ql, qr), query(rson, mid + 1, r, ql, qr));
}
int main(int argc, char const *argv[])
{
int n = read(), q = read();
rep(i, 1, n) a[i] = read();
build(1, 1, n);
while (q--)
{
int opt = read(), l = read(), r = read();
if (opt == 1)
update(1, 1, n, l, r);
else
printf("%lld\\n", query(1, 1, n, l, r).sum);
}
return 0;
}
诉状罪书:昨天推gal把CF忘得一干二净,意识到的时候罪恶感已经爬上了脊背(照样睡到日上三竿),但是9-nine天天天推得真的停不下来(兄妹相声太好玩了),最后补一句:妹妹是天!
以上是关于Codeforces Round #742 (Div. 2) 题解的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #742 div.2 A-F题解
Codeforces Round #742 div.2 A-F题解
Codeforces Round #742 (Div. 2)A-E
Codeforces Round #742 (Div. 2) E. Non-Decreasing Dilemma 线段树
Codeforces Round #742 (Div. 2) E. Non-Decreasing Dilemma 线段树
Codeforces Round #742 (Div. 2) E. Non-Decreasing Dilemma (线段树维护区间连续问题)