Codeforces Round 906 (Div. 2)
Codeforces Round 906 (Div. 2)
A. Doremy's Paint 3
解题思路:
\(a_1 + a_2 = a_2 + a_3\),所以\(a_1 = a_3\)。以此类推。所以整个序列最多出现两种不同的数字。
\(n = 2\)时,必然存在。
\(n = 3\)时,如果出现数字的种类数量小于等于2,那么必然存在。
\(n > 3\)时,若序列中只有一种数字,那么必然存在。若出现两种数字,则如果两种数字出现次数之差的绝对值小于等于1,那么必然存在。否则不存在。
代码:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void solve()
{
int n;
cin >> n;
vector<int> v(n + 1);
map<int, int> cnt;
for (int i = 1; i <= n; i++)
{
cin >> v[i];
cnt[v[i]]++;
}
if (n == 2 || cnt.size() == 1)
{
puts("YES");
return;
}
if (n == 3)
{
if (cnt.size() > 2)
{
puts("NO");
return;
}
else
{
puts("YES");
return;
}
}
if (cnt.size() >= 3)
{
puts("NO");
return;
}
sort(v.begin() + 1, v.end());
v.erase(unique(v.begin() + 1, v.end()), v.end());
if (n & 1)
{
if (abs(cnt[v[1]] - cnt[v[2]]) != 1)
{
puts("NO");
}
else
{
puts("YES");
}
}
else
{
if (abs(cnt[v[1]] - cnt[v[2]]) != 0)
{
puts("NO");
}
else
{
puts("YES");
}
}
}
int main()
{
int t = 1;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
B. Qingshan Loves Strings
解题思路:
首先,判断原字符串是否符合要求。
若符合,就是操作零次。
若不符合,我们中间统计需要操作的相邻字符的特质。即,是否存在相邻的\(0\)和相邻的\(1\)。
如果两种情况同时存在,我们必然无法通过插入\(t\)字符串是的字符串合法。因为字符串\(t\)在插入后,首尾字符必定会与\(0或1\)相连。当两种情况同时存在时,至少有一种情况插入后仍然会产生新的非法相邻字符对。
若只存在相邻的\(0\),那么如果字符串\(t\)的首尾都为\(1\)即可操作。
若只存在相邻的\(1\),那么如果字符串\(t\)的首尾都为\(0\)即可操作。
代码:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void solve()
{
int n, m;
cin >> n >> m;
string s, t;
cin >> s >> t;
m = t.size();
n = s.size();
int type = 0;
for (int i = 0; i < n - 1; i++)
{
if (s[i] == s[i + 1])
{
if (s[i] == '1' && (type < 2))
{
type += 1 << 1;
}
else if (s[i] == '0' && !(type & 1))
{
type += 1;
}
}
}
if (type != 0)
{
for (int i = 0; i < m - 1; i++)
{
if (t[i] == t[i + 1])
{
puts("NO");
return;
}
}
if (type == 3)
{
puts("NO");
}
else if (type == 2)
{
if (t[0] == t.back() && t[0] == '0')
{
puts("YES");
}
else
{
puts("NO");
}
}
else if (type == 1)
{
if (t[0] == t.back() && t[0] == '1')
{
puts("YES");
}
else
{
puts("NO");
}
}
}
else
{
puts("YES");
}
}
int main()
{
int t = 1;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
C. Qingshan Loves Strings 2
解题思路:
两个指针,一个头一个尾对比。如果当前两个位置的字符不同,则符合要求,可删去两个字符,得到更短的字符串的子问题。
如果,当前两指针相同,分情况讨论:
- 两字符都为\(0\),那么我们只能在尾指针后面插入\(01\),然后删去两个字符,得到更短的字符串的子问题。
- 两字符都为\(1\),那么我们只能在头指针前面插入\(01\),然后删去两个字符,得到更短的字符串的子问题。
如果子问题和上一个问题遇到的字符串相同,说明陷入死循环,无法操作。
按题意,如果操作次数大于\(300\),同样结束。
否则,当前字符串长度为\(0\)时,操作结束。
代码:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void solve()
{
int n;
cin >> n;
string s;
cin >> s;
string last = s;
int l = 0;
int r = n;
vector<int> v;
while (true)
{
if (s[0] == s[n - 1] && s[0] == '0')
{
s += "01";
s = s.substr(1, n);
v.push_back(r);
r++;
l++;
}
else if (s[0] == s[n - 1] && s[0] == '1')
{
s = "01" + s;
s = s.substr(1, n);
v.push_back(l);
r++;
l++;
}
else
{
n -= 2;
s = s.substr(1, n);
l++;
r--;
}
if (s == last || v.size() > 300)
{
cout << -1 << endl;
return;
}
last = s;
if (s.size() == 0 && v.size() <= 300)
{
cout << v.size() << endl;
for (auto x : v)
{
cout << x << ' ';
}
cout << endl;
return;
}
}
}
int main()
{
int t = 1;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
D. Doremy's Connecting Plan
解题思路:
如果,\(a_i < i * c\)那么必然有\(a_j \geq j * c\)。
所以,能够相连的两个点,其中有一个点必然能够与\(a_1\)相连。
所以,我们可以根据\(i * c - a_i\)排个序,从小到大判断是否和\(a_1\)所在连通块中的\(a_1\)相连。
时间复杂度:\(O(nlogn)\)
代码(\(O(nlogn)\):
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void solve()
{
ll n, c;
cin >> n >> c;
pair<ll, ll> v[n + 1];
ll sum = 0;
cin >> sum;
for (int i = 2; i <= n; i++)
{
cin >> v[i].second;
v[i].first = i;
}
sort(v + 2, v + n + 1, [&](pair<ll, ll> a, pair<ll, ll> b)
{ return a.first * c - a.second < b.first * c - b.second; });
for (int i = 2; i <= n; i++)
{
if (sum + v[i].second >= v[i].first * c)
{
sum += v[i].second;
}
else
{
puts("NO");
return;
}
}
puts("YES");
}
int main()
{
int t = 1;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
当\(a_1 + a_i \geq i * c * 1\)时,其实意味着对于所有\(a_j,(j < i)\)也都可以跟\(a_1\)相连。
因为如果能和\(i\)相连后,再于前面的点相连,意味着此时上述式子左值增大,右值减小,必然符合。
所以,我们可以直接记录一个前缀和扫过去即可。
代码\((O(n))\):
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void solve()
{
ll n, c;
cin >> n >> c;
vector<ll> a(n + 1), s(n + 1);
for (int i = 1; i <= n; i++)
{
cin >> a[i];
s[i] = s[i - 1] + a[i];
}
ll cur = 1;
for (int i = 2; i <= n; i++)
{
if (s[cur] + a[i] >= i * c)
{
cur = i;
}
}
if (cur == n)
{
puts("YES");
}
else
{
puts("NO");
}
}
int main()
{
int t = 1;
cin >> t;
while (t--)
{
solve();
}
return 0;
}

浙公网安备 33010602011771号