也许更好的阅读体验

\(\mathcal{Description}\)

小 \(D\) 正在研究魔法。

小 \(D\) 得到了远古时期的魔法咒语 \(S\),这个咒语共有 \(n\) 个音节,每个音节都可以

抽象为一个小写英文字母。

但是很快小 \(D\) 发现这个咒语并不能直接说出——它具有一定的危险性。

小 \(D\) 进行了一些仔细的研究,很快发现危险来源于 \(m\) 个禁忌词 \(T_1 , T_2 , \ldots, T_m\) 。

小 \(D\) 发现,只要说出的咒语中,连续地包含了其中某个禁忌词,那么就会带来很

大的危险。换言之,对于任意 \(1 ≤ i ≤ m\),\(T_i\) 都不能是最终说出的咒语 \(S'\) 的子串。

于是小 \(D\) 决定在原来的咒语 \(S\) 上做出一定的删减,使得它不再包含任何禁忌词。

小 \(D\) 发现如果他跳过咒语中第 \(i\) 个音节,那么咒语的威力会减少 \(a_i\) 。

小 \(D\) 想要知道,如何跳过音节可以得到一个安全的咒语,而威力的减少量最少。

值得一提的是,如果小 \(D\) 跳过了某个音节,那么与之相邻两个音节也不会变得连续。

但是小 \(D\) 并不会,请你帮帮他。

\(\mathcal{Solution}\)

先用所有的\(T\)对\(S\)做\(KMP\),得到若干个区间

那么我们的问题就转化成了有\(n\)个点和若干个区间,每个点有点权,你要选若干个点使得每个区间内都至少包含一个点,问最小点权和是多少

考虑\(DP\)

先将区间按照\(r\)升序排序

设\(f_{i,j}\)表示使前\(i\)个区间都合法,最后一个点为\(j\)的最小点权和是多少

那么对一个区间\([l_i,r_i]\),其有效的\(f\)的区间也为\([l_i,r_i]\)

考虑\(f_{i,j}\)肯定是由\(f_{i-1,k}\ k\in [l_{i-1},r_{i-1}]\)转移来的

于是我们可以去掉一维

设\(f_i\)表示最后一个点为\(i\)时的答案

然后考虑一个一个的加区间

如图,



后一个区间的蓝色部分的\(f\)值与前一个区间应是一样的

而红色区间的值则由绿色区间的值转移过来,设红色区间的一个值为\(f_k\),则有\(f_k=\min\{f_j,j\in[绿色]\}+a_k\)

我们可以用线段树查询绿色区间的最小值,并维护红色区间的增值

\(\mathcal{Code}\)

/*******************************
Author:Morning_Glory
LANG:C++
Created Time:2019年11月11日 星期一 08时24分38秒
*******************************/
#include <cstdio>
#include <fstream>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 200005;
const int maxm = 2000006;
const int inf = 0x7f7f7f7f;
//cin 省掉了快读
int n,m,tot;
int nxt[maxn],l[maxm],r[maxm],w[maxn],id[maxn];
char s[maxn],t[maxn];
bool cmp (int x,int y){ return r[x]^r[y]?r[x]<r[y]:l[x]<l[y];}
//{{{Get
void Get (char *s,int len)
{
int j=1,k=0;
reset(nxt);
while (j<=len){
if (!k||s[j]==s[k]) nxt[++j]=++k;
else k=nxt[k];
}
}
//}}}
//{{{Match
int Match (char *s,char *t)//s appears in t
{
int len=strlen(s+1);
Get(s,len);
int j=1,k=1,ans=0;
while (k<=n){
if (!j||s[j]==t[k]) ++j,++k;
else j=nxt[j];
if (j==len+1){
l[++tot]=k-len,r[tot]=k-1,id[tot]=tot;
j=nxt[j];
}
}
return ans;
}
//}}}
//{{{SegmentTree
namespace SegmentTree
{
#define cl k<<1
#define cr k<<1|1
#define lm (lt[k]+rt[k])/2
#define rm (lt[k]+rt[k])/2+1
const int maxt = 1000006;
int lt[maxt],rt[maxt],val[maxt],lazy[maxt],tag[maxt],sum[maxt];
//{{{build
void build (int l,int r,int k=1)
{
lt[k]=l,rt[k]=r,val[k]=inf;
if (l==r) return void(sum[k]=w[l]);
build(l,lm,cl);
build(rm,r,cr);
sum[k]=min(sum[cl],sum[cr]);
}
//}}}
//{{{pushdownl
void pushdownl (int k)
{
val[cl]=lazy[k]*sum[cl],val[cr]=lazy[k]*sum[cr];
lazy[cl]+=lazy[k],lazy[cr]+=lazy[k];
lazy[k]=0;
}
//}}}
//{{{pushdownt
void pushdownt (int k)
{
tag[cl]+=tag[k],tag[cr]+=tag[k];
val[cl]+=tag[k],val[cr]+=tag[k];
tag[k]=0;
}
//}}}
//{{{modify
void modify (int l,int r,int v,int k=1)
{
if (lt[k]>=l&&rt[k]<=r){
val[k]=sum[k]+v;
++lazy[k],tag[k]+=v;
return;
}
if (lazy[k]) pushdownl(k);
if (tag[k]) pushdownt(k);
if (l<=lm) modify(l,r,v,cl);
if (r>=rm) modify(l,r,v,cr);
val[k]=min(val[cl],val[cr]);
}
//}}}
//{{{query
int query (int l,int r,int k=1)
{
if (lt[k]>=l&&rt[k]<=r) return val[k];
int res=inf;
if (lazy[k]) pushdownl(k);
if (tag[k]) pushdownt(k);
if (l<=lm) res=min(res,query(l,r,cl));
if (r>=rm) res=min(res,query(l,r,cr));
return res;
}
//}}}
}
using namespace SegmentTree;
//}}}
int main()
{
scanf("%d%d",&n,&m);
scanf("%s",s+1);
for (int i=1;i<=n;++i) cin>>w[i];
for (int i=1;i<=m;++i){
scanf("%s",t+1);
Match(t,s);
}
sort(id+1,id+tot+1,cmp);
int cnt=0;
for (int i=1;i<=tot;++i){
int cur=id[i];
while (i+1<=tot&&l[id[i+1]]==l[cur]&&r[id[i+1]]==r[cur]) ++i;
id[++cnt]=cur;
}
tot=cnt; if (!tot) return printf("0\n"),0; build(1,n);
modify(l[id[1]],r[id[1]],0); for (int i=2;i<=tot;++i){
int tl=l[id[i-1]],tr=r[id[i-1]];
int lt=l[id[i]],rt=r[id[i]];
int tmp=query(tl,tr);
l[id[i]]=max(lt,tl); if (lt>tr) modify(lt,rt,tmp);
else if (rt>tr) modify(tr+1,rt,tmp);
}
printf("%d\n",query(l[id[tot]],r[id[tot]]));
return 0;
}

如有哪里讲得不是很明白或是有错误,欢迎指正

如您喜欢的话不妨点个赞收藏一下吧

魔法 [线段树优化DP]的更多相关文章

  1. Codeforces Round #426 (Div. 2) D 线段树优化dp

    D. The Bakery time limit per test 2.5 seconds memory limit per test 256 megabytes input standard inp ...

  2. BZOJ2090: [Poi2010]Monotonicity 2【线段树优化DP】

    BZOJ2090: [Poi2010]Monotonicity 2[线段树优化DP] Description 给出N个正整数a[1..N],再给出K个关系符号(>.<或=)s[1..k]. ...

  3. [AGC011F] Train Service Planning [线段树优化dp+思维]

    思路 模意义 这题真tm有意思 我上下楼梯了半天做出来的qwq 首先,考虑到每K分钟有一辆车,那么可以把所有的操作都放到模$K$意义下进行 这时,我们只需要考虑两边的两辆车就好了. 定义一些称呼: 上 ...

  4. 【bzoj3939】[Usaco2015 Feb]Cow Hopscotch 动态开点线段树优化dp

    题目描述 Just like humans enjoy playing the game of Hopscotch, Farmer John's cows have invented a varian ...

  5. POJ 2376 Cleaning Shifts (线段树优化DP)

    题目大意:给你很多条线段,开头结尾是$[l,r]$,让你覆盖整个区间$[1,T]$,求最少的线段数 题目传送门 线段树优化$DP$裸题.. 先去掉所有能被其他线段包含的线段,这种线段一定不在最优解里 ...

  6. 洛谷$P2605\ [ZJOI2010]$基站选址 线段树优化$dp$

    正解:线段树优化$dp$ 解题报告: 传送门$QwQ$ 难受阿,,,本来想做考试题的,我还造了个精妙无比的题面,然后今天讲$dp$的时候被讲到了$kk$ 先考虑暴力$dp$?就设$f_{i,j}$表示 ...

  7. D - The Bakery CodeForces - 834D 线段树优化dp···

    D - The Bakery CodeForces - 834D 这个题目好难啊,我理解了好久,都没有怎么理解好, 这种线段树优化dp,感觉还是很难的. 直接说思路吧,说不清楚就看代码吧. 这个题目转 ...

  8. 4.11 省选模拟赛 序列 二分 线段树优化dp set优化dp 缩点

    容易想到二分. 看到第一个条件容易想到缩点. 第二个条件自然是分段 然后让总和最小 容易想到dp. 缩点为先:我是采用了取了一个前缀最小值数组 二分+并查集缩点 当然也是可以直接采用 其他的奇奇怪怪的 ...

  9. Codeforces 1603D - Artistic Partition(莫反+线段树优化 dp)

    Codeforces 题面传送门 & 洛谷题面传送门 学 whk 时比较无聊开了道题做做发现是道神题( 介绍一种不太一样的做法,不观察出决策单调性也可以做. 首先一个很 trivial 的 o ...

随机推荐

  1. R = [obj for obj in recs[imagename] if obj['name'] == classname] KeyError: '007765'

    在用RFBNet做测试的时候,好几次总是遇到 R = [obj for obj in recs[imagename] if obj['name'] == classname]  KeyError: ' ...

  2. 【CSP膜你赛】柠檬的密码(manacher 二分 单调性 st表)

    题目描述 Lemon觉得他需要一个复杂的密码来保证他的帐号的安全.他经过多日思考,决定使用一个长度为奇数的回文串来作为他的密码.  但是这个回文串太长了,Lemon记不住,于是Lemon决定把它记在本 ...

  3. 浅谈 HTTP协议

    1.什么是http协议Hyper Text Transport Portocal(超文本传输协议)HTTP协议是应用层协议浏览器和web服务器通讯时遵守的约定互联网使用最多的协议提供超文本的传输服务通 ...

  4. Spring 注解@Value详解

    一.spring(基础10) 注解@Value详解[1] 一 配置方式 @value需要参数,这里参数可以是两种形式: [html] view plain copy @Value("#{co ...

  5. Http、Socket、WebSocket之间联系与区别

    WebSocket和Socket区别 可以把WebSocket想象成HTTP(应用层),HTTP和Socket什么关系,WebSocket和Socket就是什么关系. HTTP 协议有一个缺陷:通信只 ...

  6. Kibana自动关联ES索引

    原因: Kibana中关联ES索引需要手动操作,如果ES中索引较多(如每天生成),则工作量会比较大. 方法: 考虑使用Linux的cron定时器自动关联ES索引,原理是调用Kibana API接口自动 ...

  7. AWS研究热点:BMXNet – 基于MXNet的开源二进神经网络实现

    http://www.atyun.com/9625.html 最近提出的二进神经网络(BNN)可以通过应用逐位运算替代标准算术运算来大大减少存储器大小和存取率.通过显着提高运行时的效率并降低能耗,让最 ...

  8. ELK集群安装配置X-Pack

    目前使用的版本不是最新的-6.2.4,6.3以后的版本应该就是集成的了 官方资料: 在线安装步骤:https://www.elastic.co/cn/downloads/x-pack 离线安装步骤:h ...

  9. 005_Philippines之行准备

    一.去前必备的手续 (1)SSP SSP(Special Study Permit),又叫特殊学生许可,是由菲律宾移民局要求的,每一位前往菲律宾进行游学的学生都要办理的一种特殊许可,学校会统一进行办理 ...

  10. Lamda OrderBy 排序问题

    var itemModel = itemList.OrderBy(s=> decimal.Parse(s.Price)).ToList(); 前端传递的list数据金额或者其他非数字类型的字段最 ...