传送门

这个题一眼 $dp$

就是设 $f[i][0/1]$ 表示我们只考虑前 $i$ 个位置,并且保证覆盖了前 $i$ 个位置,当前位置 选/不选 的最小代价

考虑转移,设题目给出的字符串为 $s$

首先 $f[i][0]$ 必须从 $f[j][1]$ 转移过来,其中 $ j+k>=i \text{ and } s[j]=1$

然后考虑 $f[i][1]$,如果 $s[i]=1$,那么我们可以从 $f[j][0]$ 和 $f[j][1]$ 转移

并且只要保证 $i-k<=j+1$ 即可,就是保证让 $i$ 覆盖 $j+1$ 到 $i$ 这一段

然后如果 $s[i]=0$,那么我们首先可以从 $f[i-1][0/1]$ 转移

并且也可以从 $f[j][1]$ 转移,其中 $j$ 满足 $j+k>=i-1 \text{ and } s[j]=1$

注意这里的边界条件是 $j+k>=i-1$ 不是 $j+k>=i$,因为上一个站覆盖到 $i-1$ 就行了,$i$ 位置自己覆盖了

然后发现这个 $dp$ 转移暴力复杂度是 $n^2$ 的,但是可以发现对于某个位置 $i$ 的转移

对于 $f[i][0]$ ,我们要求一个区间内 $f[j][1]$ 的最小值,并且 $s[j]=1$

对于 $f[i][1]$ ,我们要求一个区间内 $f[j][0/1]$ 的最小值

所以维护两颗线段树,分别维护区间内 $f[j][1]$ 的最小值 和 区间内 $f[j][0/1]$ 的最小值

复杂度 $n \log n$

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
using namespace std;
typedef long long ll;
inline int read()
{
int x=,f=; char ch=getchar();
while(ch<''||ch>'') { if(ch=='-') f=-; ch=getchar(); }
while(ch>=''&&ch<='') { x=(x<<)+(x<<)+(ch^); ch=getchar(); }
return x*f;
}
const int N=2e5+;
const ll INF=1e18;
int n,K;
ll f[N][];
char s[N];
struct SegTree {
ll T[N<<];
SegTree () { memset(T,0x3f,sizeof(T)); }
inline void pushup(int o) { T[o]=min(T[o<<],T[o<<|]); }
void ins(int o,int l,int r,int pos,ll v)
{
if(l==r) { T[o]=min(T[o],v); return; }
int mid=l+r>>;
pos<=mid ? ins(o<<,l,mid,pos,v) : ins(o<<|,mid+,r,pos,v);
pushup(o);
}
ll query(int o,int l,int r,int ql,int qr)
{
if(l>qr||r<ql) return INF;
if(l>=ql&&r<=qr) return T[o];
int mid=l+r>>; return min(query(o<<,l,mid,ql,qr),query(o<<|,mid+,r,ql,qr));
}
}T1,T2;
int main()
{
n=read(),K=read(); scanf("%s",s+);
memset(f,0x3f,sizeof(f));
f[][]=f[][]=; T2.ins(,,n,,);
for(int i=;i<=n+;i++)
{
f[i][]=T1.query(,,n,max(,i-K),i-);
if(s[i]=='') f[i][]=T2.query(,,n,max(,i-K-),i-)+i-;
else f[i][]=min( T1.query(,,n,max(,i-K-),i-) , min(f[i-][],f[i-][]) )+i-;
T2.ins(,,n,i,f[i][]); T2.ins(,,n,i,f[i][]);
if(s[i]=='') T1.ins(,,n,i,f[i][]);
}
printf("%lld\n",min(f[n+][],f[n+][]));
return ;
}

线段树做法

这一题其实观察题目的性质,选择位置 $i$ 的代价为 $i$,也就是说代价随着位置增加

发现到这里有单调性,考虑利用单调性 $dp$

直接设 $f[i]$ 表示把 $1$ 到 $i$ 覆盖的最小代价

然后预处理出 $g[i]$ 表示从 $i$ 位置往右的第一个 $1$ 的位置

$g$ 的预处理显然,考虑 $f[i]$ 怎么转移

首先我们可以选择 $i$ 位置,那么转移显然

然后考虑 $i$ 本身不选,选择一个位置 $j$ ,使得 $j$ 能够覆盖 $i$

显然我们考虑选择的位置为 $g[i-k]$ (这里先不考虑 $i-k<1$ 的情况)

意思就是说,选择位置 $i-k$ 往右的第一个 $1$ 位置(也就是最左边能够覆盖 $i$ 的 $1$)

我们设这个位置为 $c$,考虑选择位置 $c$ 的最小花费,因为 $f$ 单调不减,最小花费即为 $f[c-k-1]+c$

发现其实我们直接贪心地选择位置 $c$ 一定比选择 $c$ 后面的某个 $1$ 更优

因为考虑后面位置代价,首先选后面本身位置的代价就比选 $c$ 大,其次选后面的话,我们最优的 $f$ 也会变大

所以后面的一定不如位置 $c$,我们直接选择位置 $c$ 转移即可

代码来自:LMOliver

(提醒一下,这个毒瘤的不知道是谁的大佬的代码本机要把 $ifdef$ 去掉不然本机 $WA$,提交 $AC$,骗无知的我去 $hack$ $qwq$)

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
//这里往下本地运行要去掉
#if (!defined(__cplusplus) || __cplusplus > 201103)
/**
* Use scanner in c++14, c++17 or c++20!
*/
template<class T>
struct Scanner{
int value;
Scanner(){
value=;
int ch;
while(isdigit(ch=getchar())){
value=value*+(ch^'');
}
}
};
Scanner<int> qaq;
#else
#endif
//这里往上本地运行要去掉
const int N=;
char s[N];
int f[N];
int n,k;
LL dp[N];
int main(){
scanf("%d%d",&n,&k);
scanf("%s",s+);
f[n+]=n+n+n;
for(int i=n;i>=;i--){
f[i]=s[i]==''?i:f[i+];
}
dp[]=;
for(int i=;i<=n;i++){
dp[i]=dp[i-]+i;
int c=f[max(i-k,)];
if(c<=i+k){
dp[i]=min(dp[i],dp[max(,c-k)-]+c);
}
}
cout<<dp[n]<<endl;
return ;
}

单调性优化dp

Codeforces 1216F. Wi-Fi的更多相关文章

  1. 【Win10 应用开发】扫描和连接Wi-fi网络

    老周今天带大家去“扫雷”了,别当真,是扫描并连接指定无线网络,时尚一点叫Wi-fi. 所以,今天的任务要求你的设备至少有1张无线网卡,目前老周没看到过有N张无线网卡的设备.像笔记本.平板等设备都可以, ...

  2. 全文检索引擎 Solr 部署与基本原理

    全文检索引擎 Solr 部署与基本原理 搜索引擎Solr环境搭建实例 关于 solr , schema.xml 的配置说明 全文检索引擎Solr系列-–全文检索基本原理 一.搜索引擎Solr环境搭建实 ...

  3. Solr搭建大数据查询平台

    参考文章:http://www.freebuf.com/articles/database/100423.html 对上面链接的补充: solr-5.5.0版本已被删除,新url:http://mir ...

  4. 我与solr(五)--关于schema.xml中的相关配置的详解

    先把文件的代码贴上来: <?xml version="1.0" encoding="UTF-8" ?> <!-- 版权说明... --> ...

  5. Solr:文本分析

    文本分析时搜索引擎的核心工作之一,对文本包含许多处理步骤,比如:分词.大写转小写.词干化.同义词转化等.简单的说,文本分析就说将一个文本字段的值转为一个一个的token,然后被保存到Lucene的索引 ...

  6. Solr:Schema设计

    本文已挪至  http://www.zhoujingen.cn/blog/8546.html Solr将数据以结构化的方式存入系统中,存储的过程中可以对数据建立索引,这个结构的定义就是通过schema ...

  7. McAfee重返科技业 研制D-Central防政府监视

    新闻链接:http://tech.qq.com/a/20131008/016127.htm 新闻时间: 10月8日编译 新闻正文:McAfee重返科技业 研制D-Central防政府监视 约翰·迈克菲 ...

  8. 【Android】 Android-wifi 直连 wifi direct wifi p2p

    现在,Android的支持Wi -Fi的直接点对点点对点(P2P)Android系统的供电设备和其他类型的设备,没有一个热点或互联网连接之间的连接.Android框架提供了一套Wi - Fi的P2P的 ...

  9. Solr Schema.xml和solrconfig.xml分析(转)

    Solr Schema.xml和solrconfig.xml分析 (http://yinwufeng.iteye.com/blog/964040) 一.字段配置(schema) schema.xml位 ...

随机推荐

  1. Centos 安装字体库 以及解决confluence 旧文档数据的乱码

    首先,第一步我们需要执行以下的命令来安装字体管理工具:  yum install -y fontconfig mkfontscale 然后我们到(Windows系统)“c:/windows/fonts ...

  2. 如何在main.js中改变vuex中的值?

    做登录权限控制的时候, 我通过全局路由守卫来去做权限判断,这样的话可能需要在整个项目加载的初期去做一些诸如 接口请求. vuex修改 之类的问题 其实非常简单,直接如图:

  3. HDU 5818 Joint Stacks ——(栈的操作模拟,优先队列)

    题意:有两个栈A和B,有3种操作:push,pop,merge.前两种都是栈的操作,最后一种表示的是如果“merge A B”,那么把B中的元素全部放到A中,且满足先入后出的栈原则. 分析:显然,我们 ...

  4. 基于Redis的分布式锁安全性分析-转

    基于Redis的分布式锁到底安全吗(上)?  2017-02-11 网上有关Redis分布式锁的文章可谓多如牛毛了,不信的话你可以拿关键词“Redis 分布式锁”随便到哪个搜索引擎上去搜索一下就知道了 ...

  5. python3笔记二十:时间操作time

    一:学习内容 time时间戳 time元组 time字符串 time时间转换图解 二:time 需要引入:import time 1.概念 UTC(世界协调时间):格林尼治天文时间,世界标准时间,在中 ...

  6. Mysql的exist与in的区别

    如果查询的两个表大小相当,那么用in和exists差别不大. 如果两个表中一个较小,一个是大表,则子查询表大的用exists,子查询表小的用in:    例如:表A(小表),表B(大表)   1: s ...

  7. Linux上安装Python3

    1. 安装支持包 yum -y groupinstall "Development tools" yum -y install zlib-devel bzip2-devel ope ...

  8. JS判定数据类型

    1.typeof                我们能够使用typeof判断变量的身份,判断字符串得到string,数字和NaN得到number,函数会得到function等,但是判断数组,对象和nu ...

  9. NDk的目录

    * docs : 开发文档* build: linux下编译的批处理命令* platform : 某种平台下编译需要的头文件和函数库* prebuild : 预编译的工具* sample: 实例代码* ...

  10. AWS EC2 外网不能访问的坑

    概述 今天我在 AWS EC2 上配置并启动了 nginx,但是通过外网不能访问,查了一下资料终于解决了,记录下来供以后开发时参考,相信对其它人也有用. 外网访问不了的原因 外网访问不了的原因不外乎有 ...