Codeforces Round 934 (Div. 2)
A - Destroying Bridges
解题思路:
完全图每个点的连边数为\(n - 1\)。
- \(k < n - 1\):都可到达。
- \(k \geq n - 1\):将点\(1\)的边删完,只能呆在点\(1\)。
代码:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using piii = pair<ll, pair<ll, ll>>;
const ll inf = 1ll << 60;
using ull = unsigned long long;
const int mod = 998244353;
void solve()
{
int n, k;
cin >> n >> k;
if (k >= n - 1)
{
cout << 1 << endl;
}
else
{
cout << n << endl;
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t = 1;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
B - Equal XOR
解题思路:
对于每个数字只有三种情况:
- 只出现在\((1, n)\)
- 只出现在\((n + 1, 2 n)\)
- 一个出现在\((1, n)\),另一个出现在\(n + 1, 2n\)
前两种情况数目肯定是相同的。
我们先用前两种成对分别填入\(l,r\)中,不够的再用第三种补,整个过程都是同步的。
代码:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using piii = pair<ll, pair<ll, ll>>;
const ll inf = 1ll << 60;
using ull = unsigned long long;
const int mod = 998244353;
void solve()
{
int n, k;
cin >> n >> k;
vector<int> a(2 * n + 2);
for (int i = 1; i <= 2 * n; i++)
{
cin >> a[i];
}
vector<int> l, r;
vector<int> vis(2 * n + 10);
// 2, 3, 4
for (int i = 1; i <= n; i++)
{
vis[a[i]] += 1;
}
for (int i = n + 1; i <= 2 * n; i++)
{
vis[a[i]] += 2;
}
vector<int> ls, rs, t;
for (int i = 1; i <= n; i++)
{
if (vis[a[i]] == 3)
{
t.push_back(a[i]);
}
else if (vis[a[i]] == 2)
{
ls.push_back(a[i]);
}
}
for (int i = n + 1; i <= 2 * n; i++)
{
if (vis[a[i]] == 4)
{
rs.push_back(a[i]);
}
}
sort(ls.begin(), ls.end());
ls.erase(unique(ls.begin(), ls.end()), ls.end());
sort(rs.begin(), rs.end());
rs.erase(unique(rs.begin(), rs.end()), rs.end());
for (int i = 0; i < min(ls.size(), rs.size()) && l.size() < 2 * k; i++)
{
l.push_back(ls[i]);
l.push_back(ls[i]);
r.push_back(rs[i]);
r.push_back(rs[i]);
}
for (int i = 0; i < t.size() && l.size() < 2 * k; i++)
{
l.push_back(t[i]);
r.push_back(t[i]);
}
// int t1 = 0;
// int t2 = 0;
for (auto x : l)
{
cout << x << ' ';
// t1 ^= x;
}
cout << "\n";
for (auto x : r)
{
cout << x << ' ';
// t2 ^= x;
}
cout << "\n";
// if (t1 == t2)
// {
// puts("YES");
// }
// // for (int i = 1; i <= n; i++)
// // {
// // t1 ^= a[i];
// // }
// for (int i = n + 1; i <= 2 * n; i++)
// {
// t2 ^= a[i];
// }
// cout << t1 << ' ' << t2 << endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t = 1;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
C - MEX Game 1
解题思路:
出现次数大于\(1\)次的,无论先后手肯定都能抢到。
所以我们按照\(mex\),从小到大优先拿出现次数为\(1\)的。
代码:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using piii = pair<ll, pair<ll, ll>>;
const ll inf = 1ll << 60;
using ull = unsigned long long;
const int mod = 998244353;
void solve()
{
int n;
cin >> n;
vector<int> a(n + 1);
map<int, int> cnt;
vector<bool> vis(n + 1);
for (int i = 1; i <= n; i++)
{
cin >> a[i];
cnt[a[i]]++;
}
for (auto t : cnt)
{
if (t.se >= 2)
{
vis[t.fi] = true;
}
}
int cur = 0;
while (vis[cur])
{
cur++;
}
for (int i = 1; i <= n; i++)
{
while (vis[cur])
{
cur++;
}
if (cnt[cur] == 1)
{
cnt[cur]--;
vis[cur] = true;
}
else
{
break;
}
while (vis[cur])
{
cur++;
}
if (cnt[cur] == 1)
{
cnt[cur]--;
}
}
int ans = 0;
while (vis[ans])
{
ans++;
}
cout << ans << endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t = 1;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
D - Non-Palindromic Substring
解题思路:
\(len = r - l + 1\):
- \(k = 1\):肯定回文。
- \(k = len\):单独判断
- \(2 \leq k \leq len - 1\):
- \(k\)为奇数:只要整个区间不是\(aba...aba\)这种交叉形式,奇数子串一定都存在。如果\(k = 3\)不存在,意味着整个区间都是\(aba...aba\)这种交叉形式。
- \(k\)为偶数:只要整个区间字符不是都一样,偶数子串一定都存在。如果\(k = 2\)不存在,意味着整个区间都是一样的。
注意:本题疑似卡了单哈希,如果要用哈希判断整体是否回文,建议使用双哈希映射。
判断整体回文:\(manacher\);双哈希
判断奇数是否存在:
- 思路一:\(f[i]:记录右侧奇偶性相同的下标中,第一个不同的字符的位置\),\((f[l] \leq r || f[l + 1]\leq r)\)。
- 思路二:哈希判断\((l, r - 2)和(l + 2, r)\)是否完全相同。
判断偶数是否存在:
- 思路一:\(f[i]:记录右侧第一个不同的字符的位置\),\((f[l] \leq r)\)。
- 思路二:区间最大最小值相同。
代码:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using piii = pair<ll, pair<ll, ll>>;
const ll inf = 1ll << 60;
using ull = unsigned long long;
const int P = 13331;
std::vector<int> manacher(std::string s)
{
std::string t = "#";
for (auto c : s)
{
t += c;
t += '#';
}
int n = t.size();
std::vector<int> r(n);
for (int i = 0, j = 0; i < n; i++)
{
if (2 * j - i >= 0 && j + r[j] > i)
{
r[i] = std::min(r[2 * j - i], j + r[j] - i);
}
while (i - r[i] >= 0 && i + r[i] < n && t[i - r[i]] == t[i + r[i]])
{
r[i] += 1;
}
if (i + r[i] > j + r[j])
{
j = i;
}
}
return r;
}
void solve()
{
int n, q;
cin >> n >> q;
string s;
cin >> s;
auto rad = manacher(s);
string str = s;
s = ' ' + s;
vector<ull> h(n + 1), p(n + 1), h1(n + 10);
p[0] = 1;
for (int i = 1; i <= n; i++)
{
p[i] = p[i - 1] * P;
h[i] = h[i - 1] * P + s[i];
}
reverse(str.begin(), str.end());
str = ' ' + str;
for (int i = 1; i <= n; i++)
{
h1[i] = h1[i - 1] * P + str[i];
}
auto get1 = [&](int l, int r) -> ull
{
return h[r] - h[l - 1] * p[r - l + 1];
};
auto get2 = [&](int l, int r) -> ull
{
return h1[r] - h1[l - 1] * p[r - l + 1];
};
vector<vector<int>> f(n + 1, vector<int>(22)), g(n + 1, vector<int>(22, 1e9));
for (int j = 0; (1 << j) <= n; j++)
{
for (int i = 1; i + (1 << j) - 1 <= n; i++)
{
if (j == 0)
{
f[i][j] = s[i];
}
else
{
f[i][j] = max(f[i][j - 1], f[i + (1 << j - 1)][j - 1]);
}
}
}
auto q1 = [&](int l, int r)
{
int len = (r - l + 1);
int k = log(len) / log(2);
return max(f[l][k], f[r - (1 << k) + 1][k]);
};
for (int j = 0; (1 << j) <= n; j++)
{
for (int i = 1; i + (1 << j) - 1 <= n; i++)
{
if (j == 0)
{
g[i][j] = s[i];
}
else
{
g[i][j] = min(g[i][j - 1], g[i + (1 << j - 1)][j - 1]);
}
}
}
auto q2 = [&](int l, int r)
{
int len = (r - l + 1);
int k = log(len) / log(2);
return min(g[l][k], g[r - (1 << k) + 1][k]);
};
while (q--)
{
int l, r;
cin >> l >> r;
ll len = r - l + 1;
ll ans = 0;
// if (len & 1)
// {
// ll t = len / 2;
// if (get1(l, l + t - 1) != get2(n - r + 1, n - (l + t + 1) + 1))
// {
// ans += len;
// }
// }
// else
// {
// ll t = len / 2;
// if (get1(l, l + t - 1) != get2(n - r + 1, n - (l + t) + 1))
// {
// ans += len;
// }
// }
// cout << ans << endl;
if (rad[l + r - 1] <= len)
{
ans += len;
}
if (q1(l, r) != q2(l, r))
{
ll up = len;
if (len & 1)
{
up--;
}
else
{
up -= 2;
}
ll k = up / 2;
ans += (2 + up) * k / 2;
}
if (len > 3 && get1(l, r - 2) != get1(l + 2, r))
{
ll up = len;
if (len & 1)
{
up -= 2;
}
else
{
up--;
}
ll k = up / 2;
ans += (3 + up) * k / 2;
}
cout << ans << "\n";
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t = 1;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
标签:int,ll,Codeforces,len,vector,long,using,Div,934
From: https://www.cnblogs.com/value0/p/18078508