鏖战字符串
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了鏖战字符串相关的知识,希望对你有一定的参考价值。
1660: 鏖战字符串
时间限制: 1 Sec 内存限制: 128 MB提交: 157 解决: 27
[提交][状态][讨论版]
题目描述
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终于放下了对名利的追逐,找到了人生的意义——吃吃吃。从此,他们过上了幸福快乐的生活……
这是一个比较复杂的动规题。套用了很多优化。
一个简单的动规:
if (check(j,i)){
dp[i]=min(dp[i],dp[j]+1LL*c*(sum[i]-sum[j])+d);
}
dp[i]=min(dp[i],dp[j]+1LL*a*(sum[i]-sum[j])*(sum[i]-sum[j])+b);
显然只能拿50分。不过这个也很好写。
完整代码:
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cstring> 5 #include<cmath> 6 #include<cstdlib> 7 #include<vector> 8 using namespace std; 9 typedef long long ll; 10 typedef long double ld; 11 typedef pair<int,int> pr; 12 const double pi=acos(-1); 13 #define rep(i,a,n) for(int i=a;i<=n;i++) 14 #define per(i,n,a) for(int i=n;i>=a;i--) 15 #define Rep(i,u) for(int i=head[u];i;i=Next[i]) 16 #define clr(a) memset(a,0,sizeof(a)) 17 #define pb push_back 18 #define mp make_pair 19 #define fi first 20 #define sc second 21 #define pq priority_queue 22 #define pqb priority_queue <int, vector<int>, less<int> > 23 #define pqs priority_queue <int, vector<int>, greater<int> > 24 #define vec vector 25 ld eps=1e-9; 26 ll pp=1000000007; 27 ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;} 28 ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;} 29 void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); } 30 //void add(int x,int y,int z){ v[++e]=y; next[e]=head[x]; head[x]=e; cost[e]=z; } 31 int dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1}; 32 ll read(){ ll ans=0; char last=‘ ‘,ch=getchar(); 33 while(ch<‘0‘ || ch>‘9‘)last=ch,ch=getchar(); 34 while(ch>=‘0‘ && ch<=‘9‘)ans=ans*10+ch-‘0‘,ch=getchar(); 35 if(last==‘-‘)ans=-ans; return ans; 36 } 37 const int inf=1<<30,N=100005; 38 ll dp[N],sum[N]; 39 char ch[N]; 40 int f[N][26],l,r,n; 41 int check(int i,int j){ 42 int Max=-inf; 43 for (int i_=0;i_<26;i_++){ 44 int c=f[j][i_]-f[i][i_]; 45 Max=max(Max,c); 46 } 47 return ((Max>=l) && (Max<=r)); 48 } 49 void Init(){ 50 for (int i=1;i<=n;i++) 51 for (int j=0;j<26;j++){ 52 f[i][j]=f[i-1][j]+((ch[i]-‘a‘)==j); 53 } 54 for (int i=1;i<=n;i++) dp[i]=inf; dp[0]=0; 55 } 56 int main(){ 57 n=read(); int a=read(),b=read(),c=read(),d=read(); l=read(),r=read(); 58 scanf("%s",ch+1); 59 for (int i=1;i<=n;i++){ 60 int t=read(); sum[i]=sum[i-1]+t; 61 } 62 if (n<=2000){ 63 Init(); 64 for (int i=1;i<=n;i++){ 65 for (int j=0;j<=i-1;j++){ 66 if (check(j,i)){ 67 dp[i]=min(dp[i],dp[j]+1LL*c*(sum[i]-sum[j])+d); 68 } 69 dp[i]=min(dp[i],dp[j]+1LL*a*(sum[i]-sum[j])*(sum[i]-sum[j])+b); 70 } 71 printf("%lld\n",dp[i]); 72 } 73 } else cout<<"FUCK"<<endl; 74 return 0; 75 }
我们来想想l>r的情况,就只有下面一种转移。
dp[i]=min(dp[i],dp[j]+1LL*a*(sum[i]-sum[j])*(sum[i]-sum[j])+b);
这不就是斜率优化,,。
我好心的放上这部分分的代码:
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cstring> 5 #include<cmath> 6 #include<cstdlib> 7 #include<vector> 8 using namespace std; 9 typedef long long ll; 10 typedef long double ld; 11 typedef pair<int,int> pr; 12 const double pi=acos(-1); 13 #define rep(i,a,n) for(int i=a;i<=n;i++) 14 #define per(i,n,a) for(int i=n;i>=a;i--) 15 #define Rep(i,u) for(int i=head[u];i;i=Next[i]) 16 #define clr(a) memset(a,0,sizeof(a)) 17 #define pb push_back 18 #define mp make_pair 19 #define fi first 20 #define sc second 21 #define pq priority_queue 22 #define pqb priority_queue <int, vector<int>, less<int> > 23 #define pqs priority_queue <int, vector<int>, greater<int> > 24 #define vec vector 25 ld eps=1e-9; 26 ll pp=1000000007; 27 ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;} 28 ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;} 29 void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); } 30 //void add(int x,int y,int z){ v[++e]=y; next[e]=head[x]; head[x]=e; cost[e]=z; } 31 int dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1}; 32 ll read(){ ll ans=0; char last=‘ ‘,ch=getchar(); 33 while(ch<‘0‘ || ch>‘9‘)last=ch,ch=getchar(); 34 while(ch>=‘0‘ && ch<=‘9‘)ans=ans*10+ch-‘0‘,ch=getchar(); 35 if(last==‘-‘)ans=-ans; return ans; 36 } 37 const int inf=1<<30,N=100005; 38 ll dp[N],sum[N]; 39 char ch[N]; 40 int f[N][26],l,r,n,Q[N],a,b,c,d; 41 int jud(int j,int k,int i){ 42 return (((dp[j]-dp[k]+a*sum[j]*sum[j]-a*sum[k]*sum[k])>=(2*a*(sum[j]-sum[k])*sum[i]))); 43 } 44 int jud_(int j,int k,int i){ 45 return ((dp[j]-dp[k]+a*sum[j]*sum[j]-a*sum[k]*sum[k])*(2*a*(sum[k]-sum[i]))>=(dp[k]-dp[i]+a*sum[k]*sum[k]-a*sum[i]*sum[i])*(2*a*(sum[j]-sum[k]))); 46 } 47 long double G(int j,int k){ 48 return ((1.0*(dp[j]-dp[k]+a*sum[j]*sum[j]-a*sum[k]*sum[k]))/(2*a*(sum[j]-sum[k]))); 49 } 50 int check(int i,int j){ 51 int Max=-inf; 52 for (int i_=0;i_<26;i_++){ 53 int c=f[j][i_]-f[i][i_]; 54 Max=max(Max,c); 55 } 56 return ((Max>=l) && (Max<=r)); 57 } 58 void Init(){ 59 for (int i=1;i<=n;i++) 60 for (int j=0;j<26;j++){ 61 f[i][j]=f[i-1][j]+((ch[i]-‘a‘)==j); 62 } 63 for (int i=1;i<=n;i++) dp[i]=inf; dp[0]=0; 64 } 65 int main(){ 66 n=read(); a=read(),b=read(),c=read(),d=read(); l=read(),r=read(); 67 scanf("%s",ch+1); 68 for (int i=1;i<=n;i++){ 69 int t=read(); sum[i]=sum[i-1]+t; 70 } 71 if (l>r){ 72 Init(); int h=1,t=1; Q[h]=0; 73 for (int i=1;i<=n;i++){ 74 while (t-h>0 && jud(Q[h],Q[h+1],i)) h++; 75 int j=Q[h]; 76 dp[i]=dp[j]+1LL*a*(sum[i]-sum[j])*(sum[i]-sum[j])+b; 77 while (t-h>0 && jud_(Q[t-1],Q[t],i)) t--; 78 Q[++t]=i; 79 printf("%lld\n",dp[i]); 80 } 81 } 82 else cout<<"FUCK"<<endl; 83 return 0; 84 }
再想想
以上是关于鏖战字符串的主要内容,如果未能解决你的问题,请参考以下文章
鏖战九载,Google 是否会因 Oracle 而弃用 Java?