题解 CF1353E K-periodic Garland
2021/4/12 10:25:37
本文主要是介绍题解 CF1353E K-periodic Garland,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
CF1353E K-periodic Garland
由题意,每个位置上有且只有 \(0/1\) 两种状态,且我们若是求出前缀和就能快速得出其中某一段中 \(1\) 的个数。
首先看一下如果让我们构造怎么构造。我们要构造一个 \(1\) 之间距离恰好为 \(k\) 的序列,就是说位置上的状态每次转移到 \(1\) ,都必须转移回到 \(0\) ,在 \(0\) 的状态呆 \(k\) 次再转移回 \(1\) 状态。
画出状态机如下:
由这个图我们先得出一个暴力且错误的状态转移方程:
\(f(i)=f(i-k)+sum(i-1)-sum(i-k)+[s_i=0]\),其中\(f(i)\) 表示构造第一位是 \(1\) 的序列需要改造的步数 ,\(sum\) 是原来序列的前缀和,\(s_i\) 是原序列。
这个东西为什么错误?因为我们不敢说第一位一定是 \(1\),说不定答案的序列开头很长一段都是 \(0\)。我们首先想到,这个问题可以大力枚举前面 \(0\) 的位数解决。假设我们把前 \(i-1\) 位设为 \(0\),第 \(i\) 位设成 \(1\) 的代价为 \(g(i)\),我们很容易得到:\(g(i)=sum(i-1)+[s_i=0]\)。
我们修改状态 \(f(i)\) 为到第 \(i\) 位为 \(1\) 时,前面均合法且至少有一个 \(1\) 的最小代价。
那么我们可以得到状态转移方程:\(f(i)=min(\ f(i-k),\ g(i-k)\ )+sum(i-1)-sum(i-k)+[s_i=0]\)。
我们的后缀仍然有可能全是 \(0\) ,所以统计答案时,我们枚举构造序列长度 \(i\) ,同时维护一个值 \(z\) 表示将以 \(i+1\) 为起点的后缀全部设为 \(0\) 的代价。答案就是 \(Min_{i=1}^nmin(\ f(i)\ ,\ g(i)\ )+z(i)\)
个人感觉难度 绿-蓝
#include <bits/stdc++.h> using namespace std; const int N=4e6+10; int f[N],g[N],sum[N]; char str[N]; int main() { int t; cin>>t; while(t--) { int n,k; cin>>n>>k>>(str+1); for(int i=0;i<=n;i++) f[i]=0x3f3f3f3f,sum[i]=0; for(int i=1;i<=n;i++) sum[i]=sum[i-1]+(str[i]-'0'), g[i]=sum[i-1]+int(str[i]=='0'); for(int i=1;i<=n;i++) if(i>k) f[i]=min(f[i-k],g[i-k])+sum[i-1]-sum[i-k]+int(str[i]=='0'); int ans=sum[n]; for(int i=1;i<=n;i++) ans=min(ans,min(f[i],g[i])+sum[n]-sum[i]); cout<<ans<<'\n'; } return 0; }
这篇关于题解 CF1353E K-periodic Garland的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-27Nacos多环境配置学习入门
- 2024-12-27Nacos快速入门学习入门
- 2024-12-27Nacos快速入门学习入门
- 2024-12-27Nacos配置中心学习入门指南
- 2024-12-27Nacos配置中心学习入门
- 2024-12-27Nacos做项目隔离学习入门
- 2024-12-27Nacos做项目隔离学习入门
- 2024-12-27Nacos初识学习入门:轻松掌握服务发现与配置管理
- 2024-12-27Nacos初识学习入门:轻松掌握Nacos基础操作
- 2024-12-27Nacos多环境配置学习入门