Codeforces Round 933 (Div. 3)

Codeforces Round 933 (Div. 3) (A~D)-CSDN博客

Codeforces Round 933 (Div. 3) (A~E)

目录:A B C D E

A题:Rudolf and the Ticket

标签: 暴力枚举(brute force)数学(math)排序算法(sortings)双指针算法(two pointers)

题目大意

  • 给一个长度为n的数组b,和一个长度为m的数组c,还有一个整数k。
  • 从b,c中各选一个数,问有多少种选法使这两个数小于等于k

思路

  • 前缀和快速得出在b数组中小于等于k - c 的数的个数

AC代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <bits/stdc++.h>
using namespace std;
const int N = 2020;
int cnt[N];
void solve()
{
int n, m, k;
cin >> n >> m >> k;
memset(cnt, 0, sizeof cnt);
for(int i = 0; i < n; i++)
{
int a; cin >> a;
cnt[a] ++;
}
for(int i = 1; i <= 2010; i ++)
cnt[i] += cnt[i-1];
int res = 0;
for(int i = 0; i < m; i++)
{
int b; cin >> b;
if(k>=b)res += cnt[k - b];
}
cout << res << endl;
}
int main()
{
int T; cin >> T;
while(T--)
solve();
return 0;
}

B题:Rudolf and 121

标签: 贪心策略(greedy)数学(math)

题目大意

  • 有一个由 n个整数组成的数组 a ,元素的编号从 1 到 n 。在一次操作中,他可以选择索引 i ( 2 ≤ i ≤ n) 并赋值:

  • ai−1=ai−1−1

  • ai=ai−2

  • ai+1=ai+1−1

  • 多次使用这个运算。问是否能将a 中元素全变为0

思路

  • 如果要将第一个数变为0,那么只能对第二个数进行操作,变换完后将不会在对第二个数进行操作。
  • 那么同理:将第二个数变为0,只能对第三个进行操作…..

AC代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <bits/stdc++.h>
using namespace std;
const int N = 1000100;
int cnt[N];
void solve()
{
int n; cin >> n;
for(int i = 1; i <= n; i++)
cin >> cnt[i];
for(int i = 1; i <= n - 2; i++)
{
if(cnt[i] > 0)
{
cnt[i+1] -= cnt[i] * 2;
cnt[i+2] -= cnt[i];
cnt[i] = 0;
}
}
for(int i = 1; i <= n; i++)
{
if(cnt[i] != 0) {
cout << "NO" << endl;
return ;
}
}
cout << "YES" << endl;
}
int main()
{
int T; cin >> T;
while(T--)
solve();
return 0;
}

C题:Rudolf and the Ugly String

标签: 动态规划(dp)字符串处理(strings)

题目大意

  • 给定字符串s,问:最少操作几次使 s 不包含子串”map”和”pie”。
  • 如果字符串 b 中存在一个连续的字符段等于 a ,则字符串 a是 b 的子串。

思路

  • 如果s中含有 “map” ,删除 ‘a’,含有”pie”,删除 ‘i’ 即可消掉
  • 特判如果含有 “mapie” 这个子串,删除 ‘p’ 即可将map和pie都消掉(只需要删一次)

AC代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <bits/stdc++.h>
using namespace std;
void solve()
{
int n; string s;
cin >> n >> s;
int t = s.size(), res = 0;
for(int i = 0; i < t - 2; i++)
{
string subS = s.substr(i, 3);
if(subS == "map" || subS == "pie")
res ++;
if(i <= t - 5 && s.substr(i, 5) == "mapie")
res--;
}
cout << res << endl;
}
int main()
{
int T; cin >> T;
while(T--)
solve();
return 0;
}

D题:Rudolf and the Ball Game

标签: 动态规划(dp)实现问题,编程技巧,模拟(implementation)

题目大意

  • n 个人编号1~n站成一个圈,有一个球在编号为x的人手上,进行m次传球
  • 给定每次投掷的距离和每次投掷的方向(顺时针或逆时针),也有可能不知道方向。
  • 计算出 m 次抛球后可能拿到球的人。

思路

  • 为了方便将编号1~n 进行减一
  • 状态表示:dp[i][j]表示 进行i次传球,球可不可能在编号为j的人手上 (值:1 0)
  • 初始值:没进行传球时球在 x ,即:dp[0][x] = 1;
  • 转态转移:
    • 逆时针传球:dp[i][j] |= dp[i-1][(j + f[i].fr) % n];
    • 顺时针传球:dp[i][j] |= dp[i-1][((j - f[i].fr) % n + n) % n];

AC代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <bits/stdc++.h>
#define fr first
#define se second
using namespace std;
typedef pair<int, char> PII;
const int N = 1010;
PII f[N];
int dp[N][N];
void solve()
{
int n, m, x;
cin >> n >> m >> x;
x--;
for(int i = 0; i <= m; i++)
for(int j = 0; j <= n; j++)
dp[i][j] = 0;
for(int i = 1; i <= m; i++)
cin >> f[i].fr >> f[i].se;
dp[0][x] = 1;
int res = 0;
for(int i = 1; i <= m; i++)
for(int j = 0; j < n; j++)
{
if(f[i].se == '?' || f[i].se == '1')
dp[i][j] |= dp[i-1][(j + f[i].fr) % n];
if(f[i].se == '?' || f[i].se == '0')
dp[i][j] |= dp[i-1][((j - f[i].fr) % n + n) % n];
if(i==m && dp[i][j]==1) res ++;
}
cout<< res << endl;
for(int i = 0; i < n; i++)
if(dp[m][i] == 1) cout << i + 1 << " ";
cout << "\n";
}
int main()
{
int T; cin >> T;
while(T--)
solve();
return 0;
}

E题:Rudolf and k Bridges

标签: 数据结构(data structures)动态规划(dp)

题目大意

  • n行和 m列组成的网格。第 i行和第 j 列的交点包含数字 a~i,j ~–相应单元格的深度。第一列和最后列中的所有单元格都与河岸相对应,因此它们的深度为 0。
  • 可以选择每一行安装支架,建造一座桥。
    1. 起点和终点必须含有支架
    1. 支架间间隔最多为d
  • 问:建造连在一起的k座桥,最少需要多少支架。

思路

  • 直接给出定义,dp[i] 为在 i 处建造支柱最小的花费。dp[i-d-1]~dp[i-1] 里面找最小值转移到dp[i]
  • 下标 i-dis-1 的位置有支柱,最远可以让下标 i 位置造一个支柱,即: dp[i]=min{ dp[i-d-1] ~ dp[i-1] } + d[i] + 1
  • 连续 k 座桥用前缀和或滑动窗口即可
  • dp这样的时间复杂度为 n * m * d 会T掉
  • 每次存储dp[i-d-1] ~ dp[i-1]最小值转移,即用单调队列优化详情看AC代码,时间复杂度 n * m

基础dp代码 (会T掉)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N = 200005;
LL d[N], ans[111];
void solve()
{
int n, m, k, dis;
cin >> n >> m >> k >> dis;
dis++;
for(int j = 1;j <= n; j++){
for(int i = 1;i <= m; i++){
cin >> d[i];
LL dd = 1e18;
for(int k = i - 1; k >= max(1, i - dis); k--)
dd = min(dd, d[k]);
if(i == 1) dd = 0;
d[i] += dd + 1;
}
ans[j] = d[m];
}
for(int i = 1;i <= n; i++)
ans[i] += ans[i-1];
LL mi = 1e18;
for(int i = k;i <= n; i++)
mi = min(mi, ans[i] - ans[i-k]);
cout << mi << '\n';
}
int main(){
int T; cin >> T;
while(T--)
solve();
return 0;
}

AC代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N = 200005;
LL d[N], ans[111], q[N];
void solve()
{
int n, m, k, dis;
cin >> n >> m >> k >> dis;
dis++;
for(int j = 1;j <= n; j++){
int hh = 0, tt = -1; //hh队列头,tt队列尾
q[0] = 0;
for(int i = 1;i <= m; i++){
cin >> d[i];
if(q[hh] < i - dis) hh++; // 队列头下标超出距离,删除队头
d[i] += d[q[hh]] + 1; // q[hh]即为dp[i-d-1] ~ dp[i-1]最小值下标
// 队列不为空,不断删除队尾比d[i]要小的值
while(tt >= hh && d[i] <= d[q[tt]])
tt--; //删除队尾
q[++tt] = i; //加入队列
}
ans[j] = d[m]; // d[m]表示在m处建造支柱的最小值即为答案
}
for(int i = 1;i <= n; i++)
ans[i] += ans[i-1];
LL mi = 1e18;
for(int i = k;i <= n; i++)
mi = min(mi, ans[i] - ans[i-k]);
cout << mi << '\n';
}
int main(){
int T; cin >> T;
while(T--)
solve();
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
//へ     /|
//  /\7    ∠_/
//  / │   / /
// │ Z _,< /   /`ヽ
// │     ヽ   /  〉
//  Y     `  /  /
// イ● 、 ●  ⊂⊃〈  /
// ()  へ    | \〈
//  >ー 、_  ィ  │ //
//  / へ   / ノ<| \\
//  ヽ_ノ  (_/  │//
//   7       |/
//
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/*
__ _,--="=--,_ __
/ \." .-. "./ \
/ ,/ _ : : _ \/` \
\ `| /o\ :_: /o\ |\__/
`-'| :="~` _ `~"=: |
\` (_) `/
.-"-. \ | / .-"-.
.---{ }--| /,.-'-.,\ |--{ }---.
) (_)_)_) \_/`~-===-~`\_/ (_(_(_) (
( )
) (
'---------------------------------------'
*/

Codeforces Round 933 (Div. 3)
https://leaf-domain.gitee.io/2024/03/12/cf-div3-933/
作者
叶域
发布于
2024年3月12日
许可协议