
Codeforces Round 891 (Div. 3) 赛后总结
小菜鸡的赛后总结

A. Array Coloring
- 题意:给出一个长度为 n 的 数组 a ,问能否将数组染上两种颜色,使得两种颜色元素总和的奇偶性相同。
- 思路:思考各种情况:1.全为奇数时,只有n为偶数才合法。2.全为偶数必定合法。2.有奇数也有偶数时,只有奇数个数为偶数才合法。因此计算奇数个数即可
void BlueFire()
{
int n;
cin >> n;
vector<int> v(n + 1);
for (int i = 1; i <= n; i++)
cin >> v[i];
int sj = 0, so = 0;
for (int i = 1; i <= n; i++)
{
if (v[i] % 2 == 0)
so++;
else
sj++;
}
if (sj % 2 == 1)
cout << "No" << endl;
else
cout << "Yes" << endl;
return;
}
B. Maximum Rounding
- 题意:给出一个整数,重新定义一个四舍五入操作,指的是如果该位>=5则进 1,且之后的位置都归 0,可进行任意次操作,求最终可以得到的整数的最大值。
- 思路:找出第一个大于5的,将其进位,然而5前面的数字如果是4则进1后还可以进,所以需要再找到第一个5前面的第一个<=3的数,让其+1,后面的全部变为0,前面的原样输出即可(注意进位10)
void BlueFire()
{
string s;
cin >> s;
string ans = "";
int index = -1;
int index_3 = -1;
for (int i = 0; i < s.length(); i++)
{
if (index == -1 && s[i] - '0' <= 3)
{
index_3 = i;
}
if (index == -1 && s[i] - '0' >= 5)
{
index = i;
}
}
if (index == -1)
{
cout << s << endl;
return;
}
if (index_3 == -1)
{
ans += '1';
for (int i = 0; i < s.length(); i++)
ans += '0';
cout << ans << endl;
return;
}
for (int i = 0; i < index_3; i++)
ans += s[i];
ans += s[index_3] + 1;
for (int i = index_3 + 1; i < s.length(); i++)
ans += '0';
cout << ans << endl;
return;
}
C. Assembly via Minimums
- 题意:给出一个数组b,数组b中的元素是由长度为n的数组a中元素两两取最小值且打乱顺序后得来的,还原一组可能的a
- 思路:首先想到一个数必定为比较n-1次,所以最小的那个数一定会在数组b中出现至少n-1次(可能有重复的情况),次小的至少n-2次...以此类推,如果出现了重复还要再额外减掉重复的个数,所以用map自动排序后,每个数应当出现的次数就应是n-res.size()-1,res存放的是当前已经有的数,这样可以同时把重复的也算上
void BlueFire()
{
int n;
cin >> n;
int l = n * (n - 1) / 2;
int maxn = -1e9;
map<int, int> mp;
for (int i = 0; i < l; i++)
{
int x;
cin >> x;
maxn = max(maxn, x);
mp[x]++;
}
vector<int> res;
for (auto [x, y] : mp)
for (int i = n - 1 - res.size(); i > 0 && y > 0; i--)
{
y -= i;
res.push_back(x);
}
for (int i = 0; i < res.size(); i++)
cout << res[i] << ' ';
for (int i = res.size(); i < n - 1; i++)
cout << maxn << ' ';
cout << 1000000000 << endl;
return;
}
D. Strong Vertices
- 题意:给出数组a和b,如果a[u] - a[v] >= b[u] - b[v],则u->v存在边,判断有多少个点满足:从该点出发,能到达所有点
- 思路:关键点就是变换一下式子:a[u] - b[u] >= a[v] - b[v],然后排序一下,最大值即为满足要求的点
void BlueFire()
{
int n;
cin >> n;
vector<int> a(n + 1);
vector<int> b(n + 1);
vector<PII> d(n + 1);
for (int i = 1; i <= n; i++)
cin >> a[i];
for (int i = 1; i <= n; i++)
{
cin >> b[i];
d[i] = {a[i] - b[i], i};
}
sort(d.begin() + 1, d.end());
int maxn = d[n].first;
vector<int> ans;
for (int i = n; i >= 1; i--)
{
if (d[i].first != maxn)
break;
ans.push_back(d[i].second);
}
cout << ans.size() << endl;
sort(ans.begin(), ans.end());
for (auto c : ans)
cout << c << " ";
cout << endl;
return;
}
F. Sum and Product
- 题意:给出一个数组a,解决q个询问:给出x,y,找到满足ai + aj = x,ai * aj = y的i,j对数
- 思路:一元二次方程...用map存一下即可,要看long double
void BlueFire()
{
int n;
cin >> n;
map<ld, ll> mp;
for (int i = 1; i <= n; i++)
{
ld x;
cin >> x;
mp[x]++;
}
int q;
cin >> q;
vector<ll> res;
for (int i = 0; i < q; i++)
{
ld x, y;
cin >> x >> y;
ld pp = (x * x - 4 * y);
if (pp < 0)
{
cout << 0 << " ";
continue;
}
ld delta = sqrt(pp);
ld g1 = (x + delta) / 2;
ld g1y = x - g1;
ll ans = 0;
ll mpg1 = mp[g1];
ll mpg1y = mp[g1y];
if (mpg1 != 0)
{
if (mpg1y != 0 && g1 != g1y)
ans += mpg1 * mpg1y;
if (g1 == g1y)
ans += (mpg1 * (mpg1 - 1)) / 2;
}
cout << ans << " ";
}
cout << endl;
return;
}