锐评
赛后两分钟就把E调出来了,赛时这两分钟浪费在哪了
A. Primary Task
题意
德米特里在黑板上写下了 t 个整数,这很好。他肯定自己丢失了其中一个重要的整数 n ,这就不好了。 整数 n 的形式是 10°x( x ≥ 2 ),其中符号” ”表示指数化。出了点差错,德米特 ^ 里在写重要整数时漏掉了符号””。例如,他应该写 105 而不是整数 1 0 5 ,应该写 1 0 19 而不是 1019 。 德米特里想知道黑板上的整数哪些可能是重要整数,哪些不可能。 \begin{aligned}&\text{德米特里在黑板上写下了 }t\text{ 个整数,这很好。他肯定自己丢失了其中一个重要的整数}\\&n\text{ ,这就不好了。}\\&\text{整数 }n\text{ 的形式是 10°x( }x\geq2\text{ ),其中符号” }\hat{\text{”表示指数化。出了点差错,德米特}}\\&\text{里在写重要整数时漏掉了符号””。例如,他应该写 }105\text{ 而不是整数 }10^5\text{,应该写}\\&10^{19}\text{ 而不是 }1019\text{ 。}\\&\text{德米特里想知道黑板上的整数哪些可能是重要整数,哪些不可能。}\end{aligned} 德米特里在黑板上写下了 t 个整数,这很好。他肯定自己丢失了其中一个重要的整数n ,这就不好了。整数 n 的形式是 10°x( x≥2 ),其中符号” ”表示指数化。出了点差错,德米特^里在写重要整数时漏掉了符号””。例如,他应该写 105 而不是整数 105,应该写1019 而不是 1019 。德米特里想知道黑板上的整数哪些可能是重要整数,哪些不可能。
输入描述
输入的第一行包含一个整数 t t t ( 1 ≤ t ≤ 1 0 4 1 \le t \le 10^4 1≤t≤104 )–棋盘上的整数个数。
接下来的 t t t 行分别包含一个整数 a a a ( 1 ≤ a ≤ 10000 1 \le a \le 10000 1≤a≤10000 ) - 即棋盘上的下一个整数。
输出描述
对于棋盘上的每个整数,如果可能是重要整数,则输出 “是”,否则输出 “否”。
您可以用任何大小写(小写或大写)输出每个字母。例如,字符串 “yEs”、“yes”、"Yes "和 "YES "将被视为肯定答案。
样例输入
7
100
1010
101
105
2033
1019
1002
样例输出
NO
YES
NO
YES
NO
YES
NO
思路
将输入的数字拆开进行查看即可,首先要一个10,后面的数字一定不能有前导零,而且不能是1。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 1e6 + 9;
const int MOD = 998244353;
int n, m;
void solve() {
string s; cin >> s;
if (s.size() >= 3) {
if (s[0] == '1' && s[1] == '0' && s[2] != '0') {
int ans = 0;
for (int i = 2; i < s.size(); ++ i) {
ans *= 10;
ans += s[i] - '0';
}
if (ans == 1) cout << "NO\n";
else cout << "YES\n";
}else cout << "NO\n";
}else {
cout << "NO\n";
}
}
signed main() {
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int _ = 1;
cin >> _;
while (_--) {
solve();
}
return 0;
}
B. Seating in a Bus
题意
在伯兰,一辆公共汽车由一排 n n n 个座位组成,座位号从 1 1 1 到 n n n 。乘客上车时请务必遵守这些规则:
- 如果车上没有空座位,乘客可以坐在任何空座位上;
- 否则,乘客应坐在至少有一个邻座空闲的座位上。换句话说,只有当索引为 i − 1 i-1 i−1 或 i + 1 i+1 i+1 的座位中至少有一个有人时,乘客才能坐在索引为 i i i ( 1 ≤ i ≤ n 1 \le i \le n 1≤i≤n) 的座位上。
今天有 n n n 位乘客上车。数组 a a a 按时间顺序记录了他们的座位号。也就是说, a 1 a_1 a1 包含了第一位乘客的座位号, a 2 a_2 a2 --第二位乘客的座位号,以此类推。
您知道数组 a a a 的内容。确定是否所有乘客都遵循了建议。
例如,如果 n = 5 n = 5 n=5 和 a a a = [ 5 , 4 , 1 , 2 , 3 5, 4, 1, 2, 3 5,4,1,2,3 ],那么建议就没有被遵守,因为 3 3 3-rd 乘客坐在了座位号为 1 1 1 的座位上,而座位号为 2 2 2 的邻座是空闲的。
输入描述
第一行输入包含一个整数 t t t ( 1 ≤ t ≤ 1 0 4 1 \le t \le 10^4 1≤t≤104 ) - 测试用例数。
下面介绍输入的测试用例。
每个测试用例的第一行都包含一个整数 n n n ( 1 ≤ n ≤ 2 ⋅ 1 0 5 1 \le n \le 2 \cdot 10^5 1≤n≤2⋅105 ) - 公交车的座位数和上车乘客数。
每个测试用例的第二行包含 n n n 个 distinct 整数 a i a_i ai ( 1 ≤ a i ≤ n 1 \le a_i \le n 1≤ai≤n ) - 按时间顺序排列的乘客座位。
保证所有测试用例的 n n n 值总和不超过 2 ⋅ 1 0 5 2 \cdot 10^5 2⋅105 ,并且没有乘客坐在已占用的座位上。
输出描述
每个测试用例的输出都单独成行:
- 如果所有乘客都遵循了建议,则输出 “YES”;
- 否则输出 “NO”。
您可以在任何情况下输出答案(例如,字符串 “yEs”、“yes”、"Yes " 和 "YES " 将被识别为肯定答案)。
样例输入
4
5
5 4 2 1 3
3
2 3 1
4
2 3 1 4
5
1 2 3 5 4
样例输出
NO
YES
YES
NO
思路
比较简单的模拟题,从第二个乘客开始,判断他上的位置左右有没有人,也就是判断他的座位号加一或者减一有没有人,如果有人的话直接输出NO,如果没人的话将这个座位号标记为已经有人。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 1e6 + 9;
const int MOD = 998244353;
int n, m, a[N];
bool st[N];
void solve() {
cin >> n;
for (int i = 1; i <= n + 9; ++ i) {
st[i] = 0;
}
for (int i = 1; i <= n; ++ i) {
cin >> a[i];
}
st[a[1]] = 1;
for (int i = 2; i <= n; ++ i) {
if (st[a[i] - 1] || st[a[i] + 1]) {
st[a[i]] = 1;
}else {
cout << "NO\n";
return;
}
}
cout << "YES\n";
}
signed main() {
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int _ = 1;
cin >> _;
while (_--) {
solve();
}
return 0;
}
C. Numeric String Template
题意
克里斯蒂娜有一个由 n n n 个整数组成的数组 a a a ,称为模板。她还有 m m m 个字符串,每个字符串都只由小写拉丁字母组成。这些字符串的编号从 1 1 1 到 m m m 。她想检查哪些字符串与模板匹配。
如果同时满足以下所有条件,则认为字符串 s s s 与模板匹配:
- 字符串 s s s 的长度等于数组 a a a 中的元素个数。
- a a a 中的相同数字对应于 s s s 中的相同符号。因此,如果 a i = a j a_i = a_j ai=aj ,那么 1 ≤ i , j ≤ n 1 \le i, j \le n 1≤i,j≤n 的 s i = s j s_i = s_j si=sj 。
- 来自 s s s 的相同符号对应于来自 s s s 的相同数字。因此,如果是 s i = s j s_i = s_j si=sj ,那么 a i = a j a_i = a_j ai=aj 就是( 1 ≤ i , j ≤ n 1 \le i, j \le n 1≤i,j≤n )。
换句话说,字符串中的字符与数组中的元素必须一一对应。
例如,如果 a a a = [ 3 , 5 , 2 , 1 , 3 3, 5, 2, 1, 3 3,5,2,1,3 ],那么字符串 "abfda "与模板相匹配,而字符串 "afbfa "则不匹配,因为字符 "f "同时对应数字 1 1 1 和 5 5 5 。
输入描述
第一行输入包含一个整数 t t t ( 1 ≤ t ≤ 1 0 4 1 \le t \le 10^4 1≤t≤104 ) - 测试用例数。
下面是测试用例的说明。
每个测试用例的第一行都包含一个整数 n n n ( 1 ≤ n ≤ 2 ⋅ 1 0 5 1 \le n \le 2 \cdot 10^5 1≤n≤2⋅105 ) - 数组 a a a 中的元素个数。
每个测试用例的第二行包含 n n n 个整数 a i a_i ai ( − 1 0 9 ≤ a i ≤ 1 0 9 -10^9 \le a_i \le 10^9 −109≤ai≤109 ) - 数组 a a a 中的元素。
每个测试用例的第三行包含一个整数 m m m ( 1 ≤ m ≤ 2 ⋅ 1 0 5 1 \le m \le 2 \cdot 10^5 1≤m≤2⋅105 ) --检查模板匹配的字符串数量。
下面是 m m m 个字符串,每个字符串都包含一个非空字符串 s j s_j sj ( 1 ≤ ∣ s j ∣ ≤ 2 ⋅ 1 0 5 1 \le |s_j| \le 2 \cdot 10^5 1≤∣sj∣≤2⋅105 ),由小写拉丁字母组成。
保证所有测试用例中 n n n 的总和不超过 2 ⋅ 1 0 5 2 \cdot 10^5 2⋅105 ,所有字符串的长度总和不超过 2 ⋅ 1 0 5 2 \cdot 10^5 2⋅105 。
输出描述
对于每个测试用例,输出 m m m 行。在 i i i-th 行( 1 ≤ i ≤ m 1 \le i \le m 1≤i≤m )输出:
- 如果索引为 i i i 的字符串与模板匹配,则输出 “YES”;
- 否则输出 “NO”。
您可以在任何情况下输出答案(例如,字符串 “yEs”、“yes”、"Yes " 和 "YES " 将被识别为肯定答案)。
样例输入
3
5
3 5 2 1 3
2
abfda
afbfa
2
1 2
3
ab
abc
aa
4
5 -3 5 -3
4
aaaa
bcbc
aba
cbcb
样例输出
YES
NO
YES
NO
NO
NO
YES
NO
YES
思路
思路比较简单,主要在于实现,实际上简单的暴力就可以做,刚开始不敢写导致浪费了很多时间。只需要判断每一个字符串大小是否等于N,并且数字相同的地方字符是否相同,字符相同的地方数字是否相两个for循环即可。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 1e6 + 9;
const int MOD = 998244353;
#define int long long
int n, m, a[N];
string s[N];
bool check(int t) {
if (s[t].size() - 1 != n) return false;
map<int,char>m3;
map<char, int>m4;
for (int i = 1; i <= n; ++ i) {
if (m3[a[i]]) {
if (m3[a[i]] != s[t][i]) {
return false;
}
}else {
m3[a[i]] = s[t][i];
}
}
for (int i = 1; i <= n; ++ i) {
if (m4[s[t][i]]) {
if (m4[s[t][i]] != a[i]) {
return false;
}
}else {
m4[s[t][i]] = a[i];
}
}
return true;
}
void solve() {
cin >> n;
int st[N];
for (int i = 1; i <= n; ++ i) {
st[i] = 0;
}
for (int i = 1; i <= n; ++ i) {
cin >> a[i];
}
cin >> m;
for (int i = 1; i <= m; ++ i) {
cin >> s[i];
s[i] = '?' + s[i];
}
for (int i = 1; i <= m; ++ i) {
if (check(i)) cout << "YES\n";
else cout << "NO\n";
}
}
signed main() {
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int _ = 1;
cin >> _;
while (_--) {
solve();
}
return 0;
}
D. Right Left Wrong
题意
弗拉德发现了一个由 n n n 个单元格组成的长条,从左到右的编号为 1 1 1 到 n n n 。在 i i i /th 单元格中,有一个正整数 a i a_i ai 和一个字母 s i s_i si ,其中所有的 s i s_i si 不是 "L "就是 “R”。
弗拉德邀请您尝试进行任意数量(可能为零)的运算,以获得尽可能高的分数。
在一次操作中,您可以选择两个索引 l l l 和 r r r ( 1 ≤ l < r ≤ n 1 \le l < r \le n 1≤l<r≤n ),这样 s l s_l sl = ‘L’, s r s_r sr = ‘R’,然后进行以下操作:
- 为当前得分加上 a l + a l + 1 + ⋯ + a r − 1 + a r a_l + a_{l + 1} + \dots + a_{r - 1} + a_r al+al+1+⋯+ar−1+ar 分;
- 将所有 l ≤ i ≤ r l \le i \le r l≤i≤r 的 s i s_i si 替换为 ‘.’, 这意味着您不能再选择这些索引。
例如,请考虑以下条带:
3 3 3 | 5 5 5 | 1 1 1 | 4 4 4 | 3 3 3 | 2 2 2 |
---|---|---|---|---|---|
L | R | L | L | R | L |
你可以先选择 l = 1 l = 1 l=1 、 r = 2 r = 2 r=2 ,然后在分数上加上 3 + 5 = 8 3 + 5 = 8 3+5=8 。
3 3 3 | 5 5 5 | 1 1 1 | 4 4 4 | 3 3 3 | 2 2 2 |
---|---|---|---|---|---|
. | . |
然后选择 l = 3 l = 3 l=3 、 r = 6 r = 6 r=6 ,并在分数上加上 1 + 4 + 3 + 2 = 10 1 + 4 + 3 + 2 = 10 1+4+3+2=10 。
3 3 3 | 5 5 5 | 1 1 1 | 4 4 4 | 3 3 3 | 2 2 2 |
---|---|---|---|---|---|
. | . | . | . | . | . |
因此,不可能再进行其他操作,最终得分是 18 18 18 。
最大得分是多少?
输入描述
第一行包含一个整数 t t t ( 1 ≤ t ≤ 1 0 4 1 \le t \le 10^4 1≤t≤104 ) - 测试用例数。
每个测试用例的第一行包含一个整数 n n n ( 2 ≤ n ≤ 2 ⋅ 1 0 5 2 \le n \le 2 \cdot 10^5 2≤n≤2⋅105 ) --条带长度。
每个测试用例的第二行包含 n n n 个整数 a 1 , a 2 , … , a n a_1, a_2, \dots, a_n a1,a2,…,an ( 1 ≤ a i ≤ 1 0 5 1 \le a_i \le 10^5 1≤ai≤105 ) - 写在条形图上的数字。
每个测试用例的第三行包含由 n n n 个字符 "L "和 "R "组成的字符串 s s s 。
保证所有测试用例中 n n n 的值之和不超过 2 ⋅ 1 0 5 2 \cdot 10^5 2⋅105 。
输出描述
对于每个测试用例,输出一个整数–可能得到的最大分数。
样例输入
4
6
3 5 1 4 3 2
LRLLLR
2
2 8
LR
2
3 9
RL
5
1 2 3 4 5
LRLRR
样例输出
18
10
0
22
思路
模拟一下什么是最好的情况,最好的情况一定是先将最内心处的LR拿掉,然后依次向外找,这样一定是结果最大的情况,我们可以反过来从外往里走,先将最外侧的拿掉,然后LR依次向里找,找里边的LR,只要找到LR就加上区间之和,区间之和可以用前缀和来实现
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 1e6 + 9;
const int MOD = 998244353;
#define int long long
int n, m, a[N], pre[N];
string s;
void solve() {
cin >> n;
for (int i = 1; i <= n; ++ i) {
cin >> a[i];
pre[i] = pre[i - 1] + a[i];
}
cin >> s;
s = '?' + s;
int ans = 0;
int j = n;
for (int i = 1; i <= n; ++ i) {
if (i >= j) break;
bool ok = false;
while (!(s[i] == 'L' && s[j] == 'R') && (i < j)) {
if (s[i] == 'R') {
ok = true;
break;
}else {
j --;
}
}
if (i >= j) break;
if (ok) continue;
ans += pre[j] - pre[i - 1];
j --;
}
cout << ans << "\n";
}
signed main() {
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int _ = 1;
cin >> _;
while (_--) {
solve();
}
return 0;
}
E. Photoshoot for Gorillas
题意
你非常喜欢大猩猩,所以决定为它们组织一次摄影活动。大猩猩生活在丛林中。丛林是由 n n n 行和 m m m 列组成的网格。 w w w 只大猩猩同意参加拍照,索引为 i i i ( 1 ≤ i ≤ w 1 \le i \le w 1≤i≤w ) 的大猩猩身高为 a i a_i ai 。您希望将所有大猩猩放入网格的单元格中,使得每个单元格中的大猩猩不超过一只。
这个排列的奇观等于边长为 k k k 的所有子方格的奇观之和。
一个子方格的奇观等于该子方格中大猩猩的高度之和。
从所有合适的排列中,选择最大的排列。
输入描述
第一行包含一个整数 t t t ( 1 ≤ t ≤ 1 0 3 1 \le t \le 10^3 1≤t≤103 )–测试用例数。 ( 1 ≤ t ≤ 1 0 3 1 \le t \le 10^3 1≤t≤103 ) - 测试用例的数量。
下面是测试用例的说明。
第一行包含整数 n n n , m m m , k k k ( 1 ≤ n , m ≤ 2 ⋅ 1 0 5 1 \le n, m \le 2 \cdot 10^5 1≤n,m≤2⋅105 , 1 ≤ n ⋅ m ≤ 2 ⋅ 1 0 5 1 \le n \cdot m \le 2 \cdot 10^5 1≤n⋅m≤2⋅105 , 1 ≤ k ≤ min ( n , m ) 1 \le k \le \min(n, m) 1≤k≤min(n,m) )–网格尺寸和正方形边长。
第二行包含一个整数 w w w ( 1 ≤ w ≤ n ⋅ m 1 \le w \le n \cdot m 1≤w≤n⋅m ) --大猩猩的数量。
第三行包含 w w w 个整数 a 1 , a 2 , … , a w a_1, a_2, \ldots, a_w a1,a2,…,aw ( 1 ≤ a i ≤ 1 0 9 1 \le a_i \le 10^9 1≤ai≤109 ) --大猩猩的高度。
保证所有测试用例中 n ⋅ m n \cdot m n⋅m 的总和不超过 2 ⋅ 1 0 5 2 \cdot 10^5 2⋅105 。同样的保证也适用于 w w w 。
输出描述
对于每个测试用例,输出一个整数–合适排列的最大奇观。
样例输入
5
3 4 2
9
1 1 1 1 1 1 1 1 1
2 1 1
2
5 7
20 15 7
9
4 1 4 5 6 1 1000000000 898 777
1984 1 1
4
5 4 1499 2004
9 5 5
6
6 7 14 16 16 6
样例输出
21
12
49000083104
3512
319
思路
实际上也不是很难是将有限的大猩猩放到我们已有的网格之中
要保证所有边长为K的子网格那个大猩猩的身高之和最大,我们可以计算每一个网格对于与整个丛林中左有边长为K的子网格的贡献。
也就是说计算每个小网格它作为多少个边长为K的子网格中的一员,那么他贡献的次数乘上这个子网格中放的大猩猩的身高就是对我们结果的贡献
共享计算的方法有很多种,我先计算出我们这个丛林中能有几行几列边长为K的子网格,那么我最后每个子网格的贡献就是,边长为K的网格在它的位置上下能滑动多少×左右能滑动多少
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 2e5 + 9;
const int MOD = 998244353;
#define int long long
int n, m, k, w, a[N];
void solve() {
cin >> n >> m >> k;
cin >> w;
for (int i = 1; i <= w; ++ i) {
cin >> a[i];
}
int t = n - k + 1, q = m - k + 1;
vector<vector<int>> d(n + 3, vector<int>(m + 5, 0));
sort(a + 1, a + 1 + w);
for (int i = 1; i <= n; ++ i) {
for (int j = 1; j <= m; ++ j) {
int x = min(t, min(k, min(n - i,i - 1) + 1)), y = min(q, min(k,min(m - j,j - 1) + 1));
d[i][j] = x * y;
}
}
priority_queue<int, vector<int>, less<int>>p1;
for (int i = 1; i <= n; ++ i) {
for (int j = 1; j <= m; ++ j) {
p1.push(d[i][j]);
}
}
int ans = 0;
for (int i = w; i >= 1; -- i) {
int tmp = p1.top();
p1.pop();
ans += tmp * a[i];
}
cout << ans << "\n";
}
signed main() {
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int _ = 1;
cin >> _;
while (_--) {
solve();
}
return 0;
}