Codeforces 900 E. Maximum Questions (DP,技巧)

Posted doggod

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 900 E. Maximum Questions (DP,技巧)相关的知识,希望对你有一定的参考价值。

题目链接:900 E. Maximum Questions 

题意:

  给出一个长度为n只含有a和b还有‘?’的串s,且‘?‘可以被任意替换为a或b。再给出一个字符串t (奇数位上为a,偶数位上为b,所以在题目中只给出了t的长度m),现在要求保证t在s中出现的次数最多的情况下面,使用‘?‘最小的情况使用了几个问号。

题解:

  拿到这个题目可以看出是DP,但是比较难以解决的就是如何确定在第i个位置时前面m个字符能够满足t,这里我看了别人的题解 ~。~哇,震惊!首先的话先对‘?’做前缀和,然后设置两个数组s[2]分别表示在第i个位置前面交叉字符串的长度,这样的话第i步结尾为a(?)满足交叉字符串的最大长度就等于第i-1步结尾为b(?)的长度加1;

1 res[i] = res[i-1] + (vec[i]==?);  // ?前缀和
2 if(vec[i] != a) s[0][i] = s[1][i-1] + 1; 
3 if(vec[i] != b) s[1][i] = s[0][i-1] + 1;

  这样我们就求出了每一步是否满足能够形成t的条件,就可以开始DP了。(如果第i步满足就判断dp[i-m]+1和dp[i-1])

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int MAX_N  = 1e5+9;
 4 char vec[MAX_N];
 5 int res[MAX_N];
 6 int s[2][MAX_N];
 7 int dp[MAX_N];
 8 int cost[MAX_N];
 9 int main()
10 {
11     int N,M,T;
12     memset(res,0,sizeof(res));
13     scanf("%d%s%d",&N,vec+1,&M); // 这里vec+1 可以把字符串赋予(1-n)
14     for(int i=1; i<=N; i++)
17     {
18         res[i] = res[i-1] + (vec[i]==?);
19         if(vec[i] != a) s[0][i] = s[1][i-1] + 1;
20         if(vec[i] != b) s[1][i] = s[0][i-1] + 1;
21         if(s[M&1][i] >= M)
22         {
23             dp[i] = dp[i-M]+1;
24             cost[i] = cost[i-M] + res[i] - res[i-M];
25         }
26         else
27         {
28             dp[i] = dp[i-1];
29             cost[i] = cost[i-1];
30         }
31         if(dp[i] <= dp[i-1])
32         {
33             if(dp[i] == dp[i-1]) cost[i] = min(cost[i],cost[i-1]);
34             else cost[i] = cost[i-1];
35         }
36     }
37     cout<<cost[N]<<endl;
38     return 0;
39 }

emmmm...这是cf大佬的写法~~ 也就比我短了一倍吧 @。@

技术分享图片
 1 #include<bits/stdc++.h>
 2 #define N 100005
 3 using namespace std;
 4 char s[N];
 5 int n,m,b[N],c[2][N];
 6 pair<int,int> f[N];
 7 int main(){
 8     scanf("%d%s%d",&n,s+1,&m);
 9     for (int i=1;i<=n;i++){
10         b[i]=b[i-1]+(s[i]==?);
11         if (s[i]!=a) c[0][i]=c[1][i-1]+1;
12         if (s[i]!=b) c[1][i]=c[0][i-1]+1;
13         if (c[m&1][i]>=m) f[i]=make_pair(f[i-m].first+1,f[i-m].second-b[i]+b[i-m]);
14         f[i]=max(f[i],f[i-1]);
15     }
16     printf("%d\n",-f[n].second);
17 }
View Code

 

以上是关于Codeforces 900 E. Maximum Questions (DP,技巧)的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #648 (Div. 2) E. Maximum Subsequence Value 贪心

Codeforces Round #648 (Div. 2) E. Maximum Subsequence Value(鸽巢原理)

Codeforces Codeforces Round #484 (Div. 2) E. Billiard

codeforces 598E E. Chocolate Bar(区间dp)

Codeforces 292 E. Copying Data (线段树)

E. Boxers ( Codeforces Round #579 )