YYHS-鏖战字符串

题目描述

Abwad在nbc即将完成她的程序的时候,急中生智拔掉了她电脑的电源线,争取到了宝贵的时间。作为著名论文《论Ctrl-C与Ctrl-V在信息学竞赛中的应用》的作者,他巧妙地使用了这种上古秘术,顺利扳回一城。

在决胜局中,Abwad决定和nbc鏖战字符串,比的是谁能更快地将一个“量子态的字符串”删除。“量子态的字符串”的每个字符都有一个删除难度dif[i]。“量子态的字符串”非常顽固,只能先分割成若干个子串,然后再通过以下两种方式删除:

1、假设子串的所有字符的删除难度之和为x,消耗a*x2+b的时间可以将子串扔进回收站。

2、若子串中出现次数最多的字符出现的次数不少于l次且不多于r次,那么采用“量子态的py自动机”算法可以消耗c*x+d的时间将子串扔进回收站。

Abwad自然知道最少用多少时间就能将字符串删去,因此,他希望你求出删去每个前缀[1,i]的最少用时。

输入

第一行七个整数n,a,b,c,d,l,r,其中n表示字符串的长度

第二行一行一个长度为n的字符串

第三行一行n个整数,表示每个字符的删除难度dif[I]

输出

n行,每行一个整数ans,表示删去前缀[1,i]最短的时间

样例输入

5 1 3 1 5 1 1 abwad 1 1 1 1 1

样例输出

4 7 8 12 13

提示

【样例解释】

以前缀[1,n]为例,将串分为a、bwad两个子串,用方法1删去第一个子串,用方法2删去第二个子串,用时1*1+3+1*4+5=13

【限制与约定】

测试点编号

n

特殊约定

1

n≤10

所有的字母都是a

2

所有的字母都是a或b

3

4

5

n≤2000

所有的字母都是a

6

所有的字母都是a或b

7

l=1,r=n

8

9

10

11

n≤100000

l=1,r=n

12

13

14

15

l>r

16

17

18

19

20

对于所有的数据,满足n≤100000,1≤a,b,c,d≤233,1≤l,r≤n,dif[i]≤50,所有字符由小写字母组成。

【后记】

在Abwad和nbc同时将最后一个子串删去时,一个带着黑色方框眼镜,方脸,穿着高腰裤的长者,乘着圣洁的祥云,飞进了YYHS的机房。在他伟大的思想的启发下,Abwad和nbc终于放下了对名利的追逐,找到了人生的意义——吃吃吃。从此,他们过上了幸福快乐的生活……

题解

这道题刚开始只想到50分的方法

自己斜率优化不怎么会,过了好久才A

这道题如果没有第二种方法就是裸的斜率优化

所以我们先考虑第一种方法,通过计算,我们可以发现

若j>k且dp[j]+a*(sum[i]-sum[j])*(sum[i]-sum[j])+b>=dp[k]+a*(sum[i]-sum[k])*(sum[i]-sum[k])+b,就可以把k弹出

通过化简可得sum[i]*2*a*(sum[j]-sum[k])>=dp[j]-dp[k]+a*sum[j]*sum[j]-a*sum[k]*sum[k]

第一种方法做完后我们就考虑第二种方法

dp[i]=min(dp[j]+(sum[i]-sum[j])*c+d)=min(dp[j]-sum[j]*c+d+sum[i]*c)

而d+sum[i]*c是一个常数,所以我们之要维护一下dp[j]-sum[j]*c就可以了,这里我们可以用堆和单调队列

因为本人不怎么会单调队列,所以用了堆。

对于判断第二种的可行性,我们可以开一个n*26的数组,可以预处理出前i个字符中所有字符的出现次数

所以每次判断一段区间是否可行的时候只要常数次操作就可以了。

 1 #include<bits/stdc++.h>
 2 #define N 100005
 3 #define ll long long
 4 #define node pair<int,int>
 5 using namespace std;
 6 ll n,a,b,c,d;
 7 int id,L,R,l,r;
 8 int w[N][‘z‘+1];
 9 int h[N];
10 ll di[N],dp[N];
11 char s[N];
12 priority_queue<node,vector<node>,greater<node> > q;
13 bool calc(int i,int j,int k){
14     return di[i]*2*a*(di[j]-di[k])>=dp[j]-dp[k]+a*di[j]*di[j]-a*di[k]*di[k];
15 }
16 bool cal(int i,int j,int k){
17     return (di[j]-di[k])*(dp[i]-dp[j]+a*di[i]*di[i]-a*di[j]*di[j])<=(di[i]-di[j])*(dp[j]-dp[k]+a*di[j]*di[j]-a*di[k]*di[k]);
18 }
19 bool ok(int id,int i){
20     int s=-1e8;
21     for (int j=‘a‘;j<=‘z‘;j++)
22         s=max(s,w[i][j]-w[id][j]);
23     if (s>=L&&s<=R) return true;
24     return false;
25 }
26 int main(){
27     scanf("%lld%lld%lld%lld%lld%d%d",&n,&a,&b,&c,&d,&L,&R);
28     scanf("%s",s+1);
29     for (int i=1;i<=n;i++){
30         for (int j=‘a‘;j<=‘z‘;j++) w[i][j]=w[i-1][j];
31         w[i][s[i]]++;
32     }
33     for (int i=1;i<=n;i++)
34         scanf("%lld",&di[i]),di[i]+=di[i-1];
35     l=0; r=0; id=0;
36     for (int i=1;i<=n;i++){
37         while (l<r&&calc(i,h[l+1],h[l])) l++;
38         dp[i]=dp[h[l]]+a*(di[i]-di[h[l]])*(di[i]-di[h[l]])+b;
39         while (id<=i)
40             if (ok(id,i)){
41                 q.push(make_pair(dp[id]-c*di[id],id));
42                 id++;
43             } else break;
44         while (!q.empty()){
45             int f=q.top().second;
46             if (ok(f,i)){
47                 dp[i]=min(dp[i],dp[f]+c*(di[i]-di[f])+d);
48                 break;
49             } else{ q.pop(); continue; }
50         }
51         printf("%lld\n",dp[i]);
52         while (l<r&&cal(i,h[r],h[r-1])) r--;
53         h[++r]=i;
54     }
55     return 0;
56 } 

时间: 2024-10-21 12:35:26

YYHS-鏖战字符串的相关文章

鏖战字符串

Abwad在nbc即将完成她的程序的时候,急中生智拔掉了她电脑的电源线,争取到了宝贵的时间.作为著名论文<论Ctrl-C与Ctrl-V在信息学竞赛中的应用>的作者,他巧妙地使用了这种上古秘术,顺利扳回一城. 在决胜局中,Abwad决定和nbc鏖战字符串,比的是谁能更快地将一个"量子态的字符串"删除."量子态的字符串"的每个字符都有一个删除难度dif[i]."量子态的字符串"非常顽固,只能先分割成若干个子串,然后再通过以下两种方式删除:

假如正则从来没来过,我们该如何去匹配一个字符串?

正则表达式其实挺难的,对于新手来说就好比一本天书.很多高端大气上档次的教程啊教材啊博客啊一般都是先列出框框条条,再来细讲,先元字符再量词再分组再反向引用.我估计是国人都受到了国外教材的影响,因为这些东西是他们整出来的.对于他们来说思路是很清晰的.老手还好,勉强能吃透.新手你没个几十遍的功夫,门都找不到在哪里.光那些规则,字母意思啊就够你喝一壶的了,你是忘了看,看了忘.(ps:本文针对javascript正则) 假如我们根本就不知道有正则这玩意儿存在,要去匹配一个字母串我们应该怎么做了?让我们也做

转:鏖战双十一-阿里直播平台面临的技术挑战(webSocket, 敏感词过滤等很不错)

转自:http://www.infoq.com/cn/articles/alibaba-broadcast-platform-technology-challenges 鏖战双十一-阿里直播平台面临的技术挑战 作者 陈康贤 发布于 2016年1月28日 | 2 讨论 分享到:微博微信FacebookTwitter有道云笔记邮件分享 稍后阅读 我的阅读清单 前言:一直以来双十一都是以交易为重心,今年当然也是如此,但是这并不妨碍万能的淘宝将双十一打造的让用户更欢乐.体验更丰富.玩法更多样.内容更有趣

条件、循环、函数定义、字符串操作练习

注意标准库的两种导入与使用方式,建议大家采用<库名>.<函数名>的方式. 对前面的代码进行优化,用for,while,if,def实现: 用循环画五角星 1 import turtle 2 3 turtle.fillcolor("red") 4 turtle.begin_fill() 5 for i in range(5): 6 turtle.forward(100) 7 turtle.right(144) 8 turtle.end_fill() 用循环画同心圆

sql常用格式化函数及字符串函数

一.常用格式化函数 1.日期转字符串 select to_char(current_timestamp, 'YYYY-MM-DD HH24:MI:SS') //2017-09-18 22:41:50 YYYY:年(4和更多位) MM:月份号(01-12) DD:一个月里的日(01-31) HH24:一天的小时数(00-23) MI:分钟(00-59) SS:秒(00-59) 2.字符串转日期 select to_date('2017-09-18','YYYY-MM-DD') //2017-09-

PHP 格式化字符串sprintf()

字符串函数 sprintf() 函数把格式化的字符串写入一个变量中 函数说明:sprintf(格式, 要转换的字符串)  参考PHP手册 返回: 格式化后的字符串 举例: 如:保留2位小数, $str = '99.9';echo sprintf('%01.2f', $str);结果为:99.90 echo round($str, 2); 结果为:99.9

js中字符串的替换

定义和用法 replace() 方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串. 语法 stringObject.replace(regexp/substr,replacement)参数 描述 regexp/substr 必需.规定子字符串或要替换的模式的 RegExp 对象. 请注意,如果该值是一个字符串,则将它作为要检索的直接量文本模式,而不是首先被转换为 RegExp 对象. replacement 必需.一个字符串值.规定了替换文本或生成替换文本的函数. 返

数组、字符串、集合

数组与集合的转换.数组与字符串的转换 ========数组变集合 String[] arr = {"abc","cc","kkkk"}; //把数组变成list集合有什么好处? /* 可以使用集合的思想和方法来操作数组中的元素. 注意:将数组变成集合,不可以使用集合的增删方法. 因为数组的长度是固定. contains. get indexOf() subList(); 如果你增删.那么会产生UnsupportedOperationExcepti

《Java编程思想》第十三章 字符串

<Java编程思想>读书笔记 1.String作为方法的参数时,会复制一份引用,而该引用所指的对象其实一直待在单一的物理位置,从未动过. 2.显式地创建StringBuilder允许预先为他指定大小.如果知道字符串多长,可以预先指定StringBuilder的大小避免多次重新分配的冲突. 1 /** 2 * @author zlz099: 3 * @version 创建时间:2017年9月1日 下午4:03:59 4 */ 5 public class UsingStringBuilder {