Educational Codeforces Round 160 (Rated for Div. 2)
Educational Codeforces Round 160 (Rated for Div. 2)
A - Rating Increase
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
typedef pair<ll, ll> pii;
#define fi first
#define se second
void solve()
{
string s;
cin >> s;
int n = s.size();
bool f = false;
string a, b;
for (int i = 1; i < n; i++)
{
if (s[i] != '0')
{
a = s.substr(0, i);
b = s.substr(i);
ll x = strtoll(a.c_str(), NULL, 10);
ll y = strtoll(b.c_str(), NULL, 10);
if (x < y)
{
f = true;
break;
}
}
}
if (f)
{
cout << a << ' ' << b << endl;
}
else
{
puts("-1");
}
}
int main()
{
int t = 1;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
B - Swap and Delete
解题思路:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
typedef pair<ll, ll> pii;
#define fi first
#define se second
void solve()
{
string s;
cin >> s;
int a = 0;
int b = 0;
int n = s.size();
vector<int> pre0(n + 1), pre1(n + 1);
s = ' ' + s;
for (int i = 1; i <= n; i++)
{
if (s[i] == '0')
{
a++;
pre0[i] = pre0[i - 1] + 1;
pre1[i] = pre1[i - 1];
}
else
{
b++;
pre0[i] = pre0[i - 1];
pre1[i] = pre1[i - 1] + 1;
}
}
if (a == pre1[n] && b == pre0[n])
{
cout << 0 << endl;
}
else
{
int cur = n;
while (true)
{
bool f = false;
while (cur > 0 && pre0[cur] < b)
{
cur--;
b--;
if (pre1[cur] == a && pre0[cur] == b)
{
f = true;
break;
}
}
while (cur > 0 && pre1[cur] < a)
{
cur--;
a--;
if (pre1[cur] == a && pre0[cur] == b)
{
f = true;
break;
}
}
if (f)
{
break;
}
}
cout << n - cur << endl;
}
}
int main()
{
int t = 1;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
C - Game with Multiset
解题思路:
记录每一个二进制数位有多少个,从低位向高位实时转换。
代码:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using i128 = __int128_t;
using piii = pair<ll, pair<ll, ll>>;
void solve()
{
vector<int> cnt(40, 0);
int n;
cin >> n;
while (n--)
{
int t, x;
cin >> t >> x;
if (t == 1)
{
cnt[x]++;
}
else
{
int cur = 0;
for (int i = 0; i <= 30; i++)
{
cur += cnt[i];
if (x >> i & 1)
{
if (cur > 0)
{
x -= 1 << i;
cur--;
}
else
{
break;
}
}
cur /= 2;
}
if (x)
{
puts("NO");
}
else
{
puts("YES");
}
}
}
}
int main()
{
int t = 1;
// cin >> t;
while (t--)
{
solve();
}
return 0;
}
D - Array Collapse
解题思路:
\(dp1[i]:考虑前i个数,以a[i]为最后一个数的方案数\)
\(dp2[i]:考虑前i个数,删去a[i]的方案数\)
\(dp1[i]\)考虑从\(dp1[1, i -1]\)转移过来。我们发现,对于\(a[i]\)最多删到前面第一个比他小的数字,设该数字下标为\(idx\).
对于\(dp1[idx, i-1]\): \(dp1[i] = dp1[i] + \sum\limits_{j = idx}^{i-1}dp1[j]\)。
对于\(dp1[1,idx -1]\):\(dp1[i] = dp1[i] + dp2[idx]\)。
代码:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using i128 = __int128_t;
using piii = pair<ll, pair<ll, ll>>;
const int mod = 998244353;
void solve()
{
int n;
cin >> n;
vector<int> a(n + 1);
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
// dp1[i]:考虑前i个数,以a[i]为最后一个数的方案数
// dp2[i]:考虑前i个数,删去a[i]的方案数
vector<ll> dp1(n + 1), dp2(n + 1), pre(n + 1);
vector<int> q(n + 1);
int hh = 0;
int tt = -1;
dp1[1] = 1;
pre[1] = 1;
q[++tt] = 1;
for (int i = 2; i <= n; i++)
{
while (hh <= tt && a[q[tt]] >= a[i])
{
tt--;
}
if (hh <= tt)
{
int idx = q[tt];
// 从(idx ~ i - 1)不同结尾转移而来 + 与idx前面的结尾链接
dp1[i] = ((pre[i - 1] - pre[idx - 1]) % mod + mod) % mod + dp2[idx];
// 前面第一个小于自己的值消掉自己 + 跟前面存在的更小值消掉自己
dp2[i] = dp1[idx] + dp2[idx];
}
else
{
// 必须保留,没法删掉
// +1是把前面全删了
dp1[i] = (pre[i - 1] + 1) % mod + mod;
dp2[i] = 0;
}
dp1[i] %= mod;
dp2[i] %= mod;
pre[i] = (pre[i - 1] + dp1[i]) % mod;
q[++tt] = i;
}
ll ans = (dp1[n] + dp2[n]) % mod;
cout << ans << endl;
}
int main()
{
int t = 1;
cin >> t;
while (t--)
{
solve();
}
return 0;
}

浙公网安备 33010602011771号