比赛链接
牛客周赛 Round 63
A题
代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e5 + 5;
const int inf = 0x3f3f3f3f3f3f3f3f;
string s;
void solve()
{
cin >> s;
if (s.size() == 2 && s[0] == s[1])
{
cout << "Yes" << endl;
}
else cout << "No" << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int test = 1;
// cin >> test;
for (int i = 1; i <= test; i++)
{
solve();
}
return 0;
}
B题
思路
n n n只有1e3,可以 n 2 n^2 n2暴力做。
代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e3 + 5;
const int inf = 0x3f3f3f3f3f3f3f3f;
int n, k;
int a[N];
void solve()
{
cin >> n >> k;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
int ans = 0;
for (int i = k; i <= n; i++)
{
int cnt = 0;
for (int low = i - k + 1, high = i; low < high; low++, high--)
{
if (a[low] != a[high]) cnt++;
}
if (cnt == 1) ans++;
}
cout << ans << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int test = 1;
// cin >> test;
for (int i = 1; i <= test; i++)
{
solve();
}
return 0;
}
C题
思路
做一遍bfs洪水填充即可。
代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e2 + 5;
const int inf = 0x3f3f3f3f3f3f3f3f;
int n, m;
int a[N][N];
int dx[2] = {0, 1}, dy[2] = {1, 0};
void solve()
{
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
cin >> a[i][j];
}
}
queue<pair<int, int>>q;
q.push({1, 1});
while (q.size())
{
int cx = q.front().first;
int cy = q.front().second;
if (cx == n && cy == m)
{
cout << "Yes" << endl;
return;
}
q.pop();
for (int i = 0; i < 2; i++)
{
int tx = cx + dx[i];
int ty = cy + dy[i];
if (tx < 1 || tx > n || ty < 1 || ty > m) continue;
if (a[tx][ty] != a[1][1]) continue;
q.push({tx, ty});
}
}
cout << "No" << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int test = 1;
cin >> test;
for (int i = 1; i <= test; i++)
{
solve();
}
return 0;
}
D题
思路
众所周知,行列式 ∣ 1 1 1 1 2 3 1 1 2 ∣ \begin{vmatrix} 1& 1& 1\\ 1& 2& 3\\ 1& 1& 2 \end{vmatrix} 111121132 的值为 1 1 1。根据行列式的性质,对其中的任意一行的元素同时乘以 x x x,则行列式的值变为 1 ∗ x 1*x 1∗x。
代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e2 + 5;
const int inf = 0x3f3f3f3f3f3f3f3f;
int x;
int a[3][3] = {{1, 1, 1}, {1, 2, 3}, {1, 1, 2}};
void solve()
{
cin >> x;
if (x == 0)
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
cout << 1 << " ";
}
cout << endl;
}
}
else
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (i == 0)
cout << x << " ";
else cout << a[i][j] << " ";
}
cout << endl;
}
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int test = 1;
// cin >> test;
for (int i = 1; i <= test; i++)
{
solve();
}
return 0;
}
E题
思路
对于字符串redreeddeer,假设我们翻转加粗的这个区间,我们将这个区间命名为 L L L。
对于 L L L左边的 r r r的数量,我们定义为 l r lr lr, L L L右边 d d d的数量我们定义为 h d hd hd。
对于 L L L内的每一个 e e e,我们选择分开进行讨论。
假设 L L L其中一个 e e e左边的 d d d的数量为 o p d opd opd,右边 r r r的数量定义为 o p r opr opr(仅限于区间 L L L内)。
则反转区间 L L L之后新增的子序列 r e d red red的数量为: ( o p r + l r ) × ( o p d + h d ) (opr+lr) \times (opd+hd) (opr+lr)×(opd+hd)。
我们定义 p r e [ ] pre[] pre[]为原始序列字符 r r r的前缀和, n x t [ ] nxt[] nxt[]为原始序列字符 d d d的后缀和。
假设当前考虑的区间 L L L中的元素 e e e的下标为 i d x idx idx。
则: o p r = p r e [ r ] − p r e [ i d x ] opr = pre[r] - pre[idx] opr=pre[r]−pre[idx], l r = p r e [ l − 1 ] lr = pre[l-1] lr=pre[l−1], o p d = n x t [ l ] − n x t [ i d x ] opd = nxt[l] - nxt[idx] opd=nxt[l]−nxt[idx], h d = n x t [ r + 1 ] hd = nxt[r+1] hd=nxt[r+1]。
则 ( o p r + l r ) × ( o p d + h d ) = ( p r e [ r ] − p r e [ i d x ] + p r e [ l − 1 ] ) × ( n x t [ l ] − n x t [ i d x ] + n x t [ r + 1 ] ) (opr+lr) \times (opd+hd) = (pre[r] - pre[idx] + pre[l-1]) \times (nxt[l] - nxt[idx] + nxt[r+1]) (opr+lr)×(opd+hd)=(pre[r]−pre[idx]+pre[l−1])×(nxt[l]−nxt[idx]+nxt[r+1])。
我们令 l o w r = p r e [ r ] + p r e [ l − 1 ] lowr = pre[r] + pre[l-1] lowr=pre[r]+pre[l−1], h i g h d = n x t [ l ] + n x t [ r + 1 ] highd = nxt[l] + nxt[r+1] highd=nxt[l]+nxt[r+1]。
对 ( p r e [ r ] − p r e [ i d x ] + p r e [ l − 1 ] ) × ( n x t [ l ] − n x t [ i d x ] + n x t [ r + 1 ] ) (pre[r] - pre[idx] + pre[l-1]) \times (nxt[l] - nxt[idx] + nxt[r+1]) (pre[r]−pre[idx]+pre[l−1])×(nxt[l]−nxt[idx]+nxt[r+1])进行拆解得到: l o w r × h i g h d − p r e [ i d x ] × h i g h d − l o w r × n x t [ i d x ] + p r e [ i d x ] × n x t [ i d x ] lowr \times highd - pre[idx] \times highd - lowr \times nxt[idx] + pre[idx] \times nxt[idx] lowr×highd−pre[idx]×highd−lowr×nxt[idx]+pre[idx]×nxt[idx]。
对于区间 L L L内所有 e e e的 l o w r lowr lowr和 h i g h d highd highd都是固定不变的,所以我们可以通过预处理得到。而对于所有的 e e e的 p r e [ i d x ] pre[idx] pre[idx]的和与 n x t [ i d x ] nxt[idx] nxt[idx]的和,我们可以分别在前缀和数组上再做一次前缀和来实现快速计算。
代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e5 + 5;
const int inf = 0x3f3f3f3f3f3f3f3f;
int n, q;
int R[N], D[N], SR[N], SD[N];
int RD[N];
int sum[N], num[N];
char s[N];
void solve()
{
cin >> n >> q;
for (int i = 1; i <= n; i++)
{
cin >> s[i];
}
for (int i = 1, j = n; i <= n; i++, j--)
{
R[i] = R[i - 1], D[j] = D[j + 1];
if (s[i] == 'r') R[i]++;
if (s[j] == 'd') D[j]++;
}
for (int i = 1, j = n; i <= n; i++, j--)
{
if (s[i] == 'e') SR[i] = R[i];
if (s[j] == 'e') SD[j] = D[j];
SR[i] += SR[i - 1], SD[j] += SD[j + 1];
}
for (int i = 1; i <= n; i++)
{
if (s[i] == 'e')
{
RD[i] = R[i] * D[i];
}
RD[i] += RD[i - 1];
}
int ans = 0;
for (int i = 1; i <= n; i++)
{
if (s[i] == 'e')
{
num[i]++;
sum[i] = (R[i - 1] * D[i + 1]);
}
num[i] += num[i - 1];
sum[i] += sum[i - 1];
}
ans = sum[n];
while (q--)
{
int l, r;
cin >> l >> r;
int cnt = num[r] - num[l - 1];
int res = ans - (sum[r] - sum[l - 1]);
int lowr = R[r] + R[l - 1], highd = D[l] + D[r + 1];
int op = cnt * lowr * highd - (SR[r] - SR[l - 1]) * highd - lowr * (SD[l] - SD[r + 1]) + (RD[r] - RD[l - 1]);
cout << res + op << endl;
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int test = 1;
// cin >> test;
for (int i = 1; i <= test; i++)
{
solve();
}
return 0;
}
F题
思路
没做出来,过两天补上…