Codeforces Round 642 (Div3)
K-periodic Garland
给定一个长度位\(n\)的\(01\)串,每次操作可以将\(1\)变为\(0\)或者将\(0\)变为\(1\),现在你需要通过操作使得所有\(1\)之间的距离为\(k\),求最少的操作次数,注意全为\(0\)也算
\(1<=n<=1e6,1<=k<=n\)
题解:\(dp\) / 贪心 : 最大子段和思想
方法一:\(dp\) \(O(n)\)
状态表示:\(f[i][0/1]\):代表将区间\([1,i]\)变为合法串的最小操作次数,且第\(i\)位为\(0/1\)
状态转移:
- 贪心考虑只有两种情况的时候我们可以将第\(i\)位变成\(1\):
- 若第\(i-k\)位也是\(1\),我们可以考虑将第\(i\)位变为\(1\),那么我们需要将\([i-k+1,i-1]\)中的所有1变为0
- 我们同样可以考虑使第\(i\)位前面所有的1变为0,从第\(i\)位的\(1\)重新当作起始位置,那么我们需要将前面所有的1变为0
- 同时如果该位本身不是\(1\),我们需要将其变为\(1\)
\(f[i][1]=min(f[i][1]+pre[i-1]-pre[i-k],pre[i-1]) + (s[i]=='0')\)
- 同样只有两种情况我们可以将第\(i\)位变为\(0\):
- 第\(i-1\)位是1的情况
- 第\(i-1\)位是0的情况
- 如果第\(i\)位不是0,我们需要将其变为0
\(f[i][0]=min(f[i-1][1],f[i-1][0])+(s[i]=='1')\)
状态初始:\(f[i]=0\)
方法二:贪心 + 枚举对\(k\)余数 \(复杂度:调和级数O(nlogn)\)
由题意可知这些\(1\)一定是连续的且距离间隔\(k\),这说明1所处的位置对\(k\)取模的模数是相同的,且这些1连续,所以我们可以考虑根据对\(k\)的余数来枚举\(1\)的起始位置,所以我们不妨先将所有的1变为0
我们设\(cnt\):可以减免的答案贡献,或者说从起始位置到现在1的前缀和数量与0的前缀和数量之差;
- 对于某一位来说,我们需要其为1,并且其本身已经为1,说明我们原本不用将其变为0,所以这部分答案可以减免,\(cnt\)++,
- 对于某一位来说,我们需要其为1,但是其本身为0,说明我们这部分答案不能减免,\(cnt\)--,
- 如果\(cnt<0\),说明从起始位置开始0的数量已经比1的数量多了,也就是说我们将这些前面位置都变成1就比全部变为0吃亏,倒不如全部变为0,借用最大子段和的思想我们直接舍弃前面的部分,将该位置重新当成起始位置,\(cnt=0\)
- 我们在枚举过程中始终维护\(cnt\)的最大值即可
时间复杂度为调和级数:\(O(nlogn)\)
#include <bits/stdc++.h>
#define Zeoy std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0)
#define debug(x) cerr << #x << '=' << x << endl
#define all(x) (x).begin(), (x).end()
#define rson id << 1 | 1
#define lson id << 1
#define int long long
#define mpk make_pair
#define endl '\n'
using namespace std;
typedef unsigned long long ULL;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-9;
const int N = 1e6 + 10, M = 4e5 + 10;
int n, k;
int f[N][2];
int pre[N];
void solve()
{
cin >> n >> k;
string s;
cin >> s;
s = " " + s;
for (int i = 1; i <= n; ++i)
pre[i] = pre[i - 1] + (s[i] == '1');
for (int i = 1; i <= n; ++i)
{
f[i][1] = min(f[max(0ll, i - k)][1] + pre[i - 1] - pre[max(0ll, i - k)], pre[i - 1]) + (s[i] == '0');
f[i][0] = min(f[i - 1][1], f[i - 1][0]) + (s[i] == '1');
}
cout << min(f[n][0], f[n][1]) << endl;
}
signed main(void)
{
Zeoy;
int T = 1;
cin >> T;
while (T--)
{
solve();
}
return 0;
}
#include <bits/stdc++.h>
#define Zeoy std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0)
#define debug(x) cerr << #x << '=' << x << endl
#define all(x) (x).begin(), (x).end()
#define rson id << 1 | 1
#define lson id << 1
#define int long long
#define mpk make_pair
#define endl '\n'
using namespace std;
typedef unsigned long long ULL;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-9;
const int N = 1e6 + 10, M = 4e5 + 10;
int n, k;
void solve()
{
cin >> n >> k;
string s;
cin >> s;
s = " " + s;
int ans = 0;
for (int i = 1; i <= n; ++i)
if (s[i] == '1')
ans++;
int maxx = -INF;
for (int i = 1; i <= k; ++i)
{
int cnt = 0;
for (int j = i; j <= n; j += k)
{
if (s[j] == '1')
cnt++;
else
cnt--;
if (cnt < 0)
cnt = 0;
maxx = max(cnt, maxx);
}
}
cout << ans - maxx << endl;
}
signed main(void)
{
Zeoy;
int T = 1;
cin >> T;
while (T--)
{
solve();
}
return 0;
}
Decreasing Heights
给出一个 \(n \times m\) 的矩阵,每个矩阵的权值代表该点的初始高度。
现在需要从点 \(( 1 , 1 )\) 走到点 \(( n , m )\) ,每一步需要满足以下条件:
- 只能向右或向下
- 设当前格子的高度为 \(x\) ,只能移动到高度为 \(x + 1\) 的格子上去
初始时可以进行操作,使得某个格子的高度减少一个单位。
问最少需要进行多少次操作,可以存在至少一条从点 \(( 1 , 1 )\) 到点 \(( n , m )\) 的路线
\(1≤n,m≤100\)
题解:\(dp\) + 枚举
我们发现只要确定起点\((1,1)\)的高度,那么对于任意位置\((i,j)\)的高度我们都是确定的:\(i+j-2\),所以我们只需要枚举起点的高度即可,但是我们怎么枚举?
我们贪心的进行枚举,每次枚举的起点高度能够保证使得位置\((i,j)\)上的高度不需要降低,即起码保证有一个位置我们不需要改变其高度,如果这个位置原有的高度\(h\),且\(h<a[1][1]+i+j-2\),说明我们不能通过降低起点的高度使得到达\((i,j)\)时不需要降低\((i,j)\)的高度,否则我们可以利用\(dp\)求出从起点到终点的最小操作次数
设起点高度为\(h\)
状态表示:\(f[i][j]\):从起点\((1,1)\)到达\((i,j)\)所需的最小操作次数
状态转移:
- 该位置是从上面过来的,即\((i-1,j)->(i,j)\)
\(f[i][j] = min(f[i][j],f[i-1][j]+a[i][j]-(h+i+j-2)),a[i][j]>=h+i+j-2\)
- 该位置是从右边过来的,即\((i,j-1)->(i,j)\)
\(f[i][j] = min(f[i][j],f[i][j-1]+a[i][j]-(h+i+j-2)),a[i][j]>=h+i+j-2\)
- 如果$ a[i][j]<h+i+j-2 \(,说明位置\)(i,j)$无法到达,我们直接跳过即可
#include <bits/stdc++.h>
#define Zeoy std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0)
#define debug(x) cerr << #x << '=' << x << endl
#define all(x) (x).begin(), (x).end()
#define rson id << 1 | 1
#define lson id << 1
#define int long long
#define mpk make_pair
#define endl '\n'
using namespace std;
typedef unsigned long long ULL;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-9;
const int N = 1e2 + 10, M = 4e5 + 10;
int n, m;
int a[N][N];
int calc(int x, int y)
{
vector<vector<int>> f(n + 10, vector<int>(m + 10, INF));
int h = a[x][y] - x - y + 2;
f[1][1] = a[1][1] + x + y - 2 - a[x][y];
for (int i = 1; i <= n; ++i)
{
for (int j = 1; j <= m; ++j)
{
int cur = h + i + j - 2;
if (cur > a[i][j])
continue;
f[i][j] = min(f[i][j], f[i - 1][j] + a[i][j] - cur);
f[i][j] = min(f[i][j], f[i][j - 1] + a[i][j] - cur);
}
}
return f[n][m];
}
void solve()
{
cin >> n >> m;
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
cin >> a[i][j];
int ans = INF;
for (int i = 1; i <= n; ++i)
{
for (int j = 1; j <= m; ++j)
{
if (a[1][1] + i + j - 2 < a[i][j])
continue;
ans = min(ans, calc(i, j));
}
}
cout << ans << endl;
}
signed main(void)
{
Zeoy;
int T = 1;
cin >> T;
while (T--)
{
solve();
}
return 0;
}
Codeforces Round 642 (Div3)的更多相关文章
- 【赛时总结】◇赛时·V◇ Codeforces Round #486 Div3
◇赛时·V◇ Codeforces Round #486 Div3 又是一场历史悠久的比赛,老师拉着我回来考古了……为了不抢了后面一些同学的排名,我没有做A题 ◆ 题目&解析 [B题]Subs ...
- CodeForces Round #527 (Div3) B. Teams Forming
http://codeforces.com/contest/1092/problem/B There are nn students in a university. The number of st ...
- CodeForces Round#480 div3 第2场
这次div3比上次多一道, 也加了半小时, 说区分不出1600以上的水平.(我也不清楚). A. Remove Duplicates 题意:给你一个数组,删除这个数组中相同的元素, 并且保留右边的元素 ...
- CODEFORCES ROUND#624 DIV3
这次比赛从名字就可以看出非常水,然鹅因为第一次打codeforces不太熟悉操作只来的及做签到题(还错了一次) A,B,C都是签到题考点思维就不写了 D题 https://codeforces.ml/ ...
- A. Launch of Collider Codeforces Round #363 (Div2)
A. Launch of Collider time limit per test 2 seconds memory limit per test 256 megabytes input standa ...
- CodeForces Round #527 (Div3) D2. Great Vova Wall (Version 2)
http://codeforces.com/contest/1092/problem/D2 Vova's family is building the Great Vova Wall (named b ...
- CodeForces Round #527 (Div3) D1. Great Vova Wall (Version 1)
http://codeforces.com/contest/1092/problem/D1 Vova's family is building the Great Vova Wall (named b ...
- CodeForces Round #527 (Div3) C. Prefixes and Suffixes
http://codeforces.com/contest/1092/problem/C Ivan wants to play a game with you. He picked some stri ...
- CodeForces Round #527 (Div3) A. Uniform String
http://codeforces.com/contest/1092/problem/A You are given two integers nn and kk. Your task is to c ...
- 「暑期训练」「Brute Force」 Optimal Point on a Line (Educational Codeforces Round 16, B)
题意 You are given n points on a line with their coordinates $x_i$. Find the point x so the sum of dis ...
随机推荐
- Mongodb入门2
$push 修饰符:用于往数组中追加元素 db.workmates.update({name:'xiaowang'},{$push:{interseta:"PHP"}}) ...
- C++ char*类型与vector类型的相互转换
char*类型与vector<char> 类型的相互转换 很多时候需要使用动态的字符串,但是char*难以完成相应的扩容操作,而动态数组vector则可以简单地完成,结合二者特性就可以完成 ...
- MybatisPlus——DML编程控制——增删改
DML编程控制 id生成策略控制 不同的表应用不同的id生成策略 日志:自增(1,2,3,4,......) 购物订单:特殊规则(FQ23948AK3843) 外卖单:关联地区日期等信息(10 04 ...
- nexus 部署与设置
安装nexus df -h 先查看目录磁盘空间,我安装的版本占用了四个G 空间,目录文件空间不够导致启动失败 上传 nexus 压缩包,并解压 查询 8081 端口号是否被占用 sudo netsta ...
- 如何关闭每次打开启动软件前的弹窗(用户账户控制)你要允许此应用.WIN11、10、7
1.先点击任务栏内的搜索,输入"控制面板",然后点开 2.然后在右上角输入"更改用户",然后在下方点击"更改用户账户控制设置" 3.然后把& ...
- Spring技术书的代码资源下载
我是清华社编辑,这些资源获得作者授权,免费提供给读者个人学习使用.禁止任何形式的商用. 二维码用微信扫,按提示填写你的邮箱,转到电脑上打开邮箱下载.清华国企网盘,比较快速.安全.放心下载. 百度网盘链 ...
- LeetCode 1397. Find All Good Strings 找到所有好字符串 (数位DP+KMP)
好题- 就是比平时的 hard 难了一些-- 虽然猜出是数位DP了-不过比我之前做的题,好像多了一维,印象中都是一维记录之前状态就够了--然后就没做出-- 至于 KMP 的应用更是神奇,虽然掌握的 k ...
- Perfetto分析进阶
一.Perfetto介绍 Perfetto是Android Q中引入的全新下一代平台级跟踪工具,为Android.Linux和Chrome平台提供了一种通用的性能检测和跟踪分析工具集.其核心是引入了一 ...
- Vue中mixins(混入)的介绍和使用
为什么引进 mixins 随着项目的开发,组件越来越多 ,这就导致了在各个组件中需要编写功能相同的代码段,重复地定义这些相同的属性和方法,导致代码地冗余,还不利于后期代码的维护 混入mixins 的创 ...
- Vulhub 安装运行
前言 vulhub是利用docker技术做的一个漏洞复现平台,可以一键搭建对应的配置.在下载好对应的代码包后,不需要安装,只需要解压并利用3条命令,就可以简单的创建关闭对应漏洞环境.最好是购买一台阿里 ...