码迷,mamicode.com
首页 > 其他好文 > 详细

鏖战字符串

时间:2017-09-17 22:17:07      阅读:172      评论:0      收藏:0      [点我收藏+]

标签:字符串   eof   php   思想   cstring   生活   etc   tab   内存   

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 } 
View Code

我们来想想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 } 
View Code

再想想

鏖战字符串

标签:字符串   eof   php   思想   cstring   生活   etc   tab   内存   

原文地址:http://www.cnblogs.com/SXia/p/7537747.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!