346
A - Adjacent Product
签到
void solve() {
int n;cin >> n;vector<int> a(n);
for (int i = 0;i < n;i++)cin >> a[i];
for (int i = 0;i < n-1;i++) {
cout << a[i] * a[i + 1] << " ";
}
}
B - Piano
有一个无限长的钢琴键盘。在这个键盘中,是否存在一个由
个白键和 个黑键组成的连续部分?
假设 wbwbwwbwbwbw
构成的字符串。
在 w
和 b
组成的子串?
什么是
暴力即可
void solve() {
int w, b;cin >> w >> b;
string s = "wbwbwwbwbwbw";
for (int i = 1;i <= 10;i++) {
s += s;
if (s.size() > 200)break;
}
for (int i = 0;i < s.size();i++) {
for (int j = 1;j < s.size() - i;j++) {
string ss = s.substr(i, j);
if (count(ss.begin(), ss.end(), 'w') == w && count(ss.begin(), ss.end(), 'b') == b) {
cout << "Yes\n";return;
}
}
}
cout << "No\n";
}
C - Σ
长度为
求
#define int long long
void solve() {
int n, k;cin >> n >> k;vector<int>a(n);
map<int, int> mp;
for (int i = 0;i < n;i++)cin >> a[i], mp[a[i]]++;
int p = 0;
for (auto [x, y] : mp) {
if (x <= k)
p += x;
}
int kk = (1 + k) * k / 2;
cout << kk - p << '\n';
}
D - Gomamayo Sequence
给你一个长度为 0
和 1
组成。
长度为 0
和 1
组成,当且仅当它满足以下条件时,它是一个**好的字符串:
- 恰好有一个整数
使得 与 中的 -3 和 -3 字符相同。
对于每个
- 如果
的 个字符是 "0",则将其替换为 "1",反之亦然。如果执行此操作,代价为 。
求使
Solution
前缀后缀和
可以知道,除了
#define int long long
void solve() {
int n;cin >> n;string s;cin >> s;vector<int> a(n + 1);s = ' ' + s;
for (int i = 1;i <= n;i++)cin >> a[i];
vector<array<int, 2>> f(n + 2), g(n + 2);
for (int i = 1;i <= n;i++) {
f[i][0] = f[i - 1][1] + (s[i] == '0' ? 0 : a[i]);
f[i][1] = f[i - 1][0] + (s[i] == '1' ? 0 : a[i]);
}
int ans = 1e18;
for (int i = n;i >= 2;i--) {
g[i][0] = g[i + 1][1] + (s[i] == '0' ? 0 : a[i]);
g[i][1] = g[i + 1][0] + (s[i] == '1' ? 0 : a[i]);
ans = min(ans, f[i - 1][0] + g[i][0]);
ans = min(ans, f[i - 1][1] + g[i][1]);
}
cout << ans << '\n';
}
E - Paint
有一个行数为
您将按照
-
如果是
,则使用颜色 重新绘制 /-th 行中的所有单元格。 -
如果是
,则用颜色 重新绘制 /th 列中的所有单元格。
完成所有操作后,针对网格中存在的每种颜色
Solution
逆向思维
从后往前遍历,就不需要讨论的非常复杂,且后面的一定是最终的,不用担心被覆盖的问题。
#define int long long
void solve() {
int n, m, q;cin >> n >> m >> q;
vector<int> t(q + 1), a(q + 1), x(q + 1), visn(n + 1), vism(m + 1);
for (int i = 1;i <= q;i++) {
cin >> t[i] >> a[i] >> x[i];
}
int n1 = n, m1 = m;
vector<int> cnt(2e5 + 1);
for (int i = q;i >= 1;i--) {
if (t[i] == 1) {
if (!visn[a[i]]) {
n1--;
visn[a[i]] = 1;
cnt[x[i]] += m1;
}
} else {
if (!vism[a[i]]) {
m1--;
vism[a[i]] = 1;
cnt[x[i]] += n1;
}
}
}
cnt[0] += n1 * m1;
vector<pair<int, int>> ans;
for (int i = 0;i <= 2e5;i++) {
if (cnt[i]) {
ans.push_back({i,cnt[i]});
}
}
cout << ans.size() << '\n';
for (auto [x, y] : ans)cout << x << " " << y << '\n';
}
F - SSttrriinngg in StringString
对于长度为
例如,如果 abc
,那么 abcabc
,aaabbbccc
。同时,对于任意字符串
给定正整数
始终是 的子序列。
Solution
二分+贪心
固定 k 并考虑如何确定 g (T,k)是否为 f (S,N)的子串。
让 s 为 S 的长度,t 为 T 的长度,
让我们依次找到以下值,以 i=1,2,...,t 的顺序:
:最小的 j,使得 是 的子串。
最终,通过比较从 N×s 得到的
:给定正整数 a 和 b 以及字符 c,在 f (S,N)的第 a 个字符(包括它自己)之后,找到字符 c 的第 b 次出现的位置。
假设 c 在 S 中出现了
因此,只需处理满足条件 a≤s,b≤
因此,包括最初提到的对 k 的二进制搜索,问题可以在总共
(待更
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
const int INF = 0x3f3f3f3f;
const LL mod = 1e9 + 7;
const int N = 200005;
char s[N], t[N];
int a[N][26];
vector<int> b[26];
int main() {
LL n;
scanf("%lld%s%s", &n, s + 1, t + 1);
int m = strlen(s + 1);
for (int i = 1; i <= m; i++) {
for (int j = 0; j < 26; j++) a[i][j] = a[i - 1][j];
a[i][s[i] - 'a']++;
b[s[i] - 'a'].push_back(i);
}
LL l = 1, r = 1e17 + 500;
while (l < r) {
LL mid = l + r >> 1;
LL k = 0, z = 0;
int ok = 0;
for (int i = 1; t[i] && k < n; i++) {
int c = a[m][t[i] - 'a'];//在s字符串中这个字母的个数<->int c = b[t[i] - 'a'].size();
if (c == 0) {//若没有这个字符,则直接结束(这个mid作为答案不符合要求,答案应该更小)
k = n;break;
}
LL x = a[z][t[i] - 'a'] + mid;
k += (x - 1) / c;
x = (x - 1) % c + 1;
z = b[t[i] - 'a'][x - 1];//记录在满足条件的最后一个周期中的下标
}
if (k >= n)
//若已经经过超过了n轮,还没能将t字符串走完,则证明无法满足要求,这种二分的目标是找出第一个满足k>=n的下标
r = mid;
else
l = mid + 1;
}
printf("%lld\n", l - 1);
return 0;
}