Codeforces-1297F:New Year and Handle Change(wqs二分)

F. New Year and Handle Change
time limit per test 3 seconds
memory limit per test 256 megabytes
inputstandard input
outputstandard output

New Year is getting near. So it’s time to change handles on codeforces. Mishka wants to change his handle but in such a way that people would not forget who he is.

To make it work, he only allowed to change letters case. More formally, during one handle change he can choose any segment of his handle [ i ; i + l − 1 ] [i;i+l−1] [i;i+l1] and apply tolower or toupper to all letters of his handle on this segment (more fomally, replace all uppercase letters with corresponding lowercase or vice versa). The length l l l is fixed for all changes.

Because it is not allowed to change codeforces handle too often, Mishka can perform at most k k k such operations. What is the minimum value of min(lower,upper) (where lower is the number of lowercase letters, and upper is the number of uppercase letters) can be obtained after optimal sequence of changes?

Input
The first line of the input contains three integers n n n, k k k and l l l ( 1 ≤ n , k , l ≤ 1 0 6 , l ≤ n ) (1≤n,k,l≤10^6,l≤n) (1n,k,l106,ln) — the length of Mishka’s handle, the number of changes and the length of the segment.

The second line of the input contains one string s s s, consisting of n n n lowercase and uppercase Latin letters — Mishka’s handle.

Output
Print one integer — the minimum value of min(lower,upper) after that Mishka change his handle at most k times in a way described in the problem statement.

Examples
input
7 1 4
PikMike
output
0
input
15 2 2
AaAaAAaaAAAAaaA
output
2
input
14 2 6
aBcdEFGHIJklMn
output
0
input
9 2 2
aAaAAAaaA
output
1

思路:可以将题目化简为给出 k k k条长度为 l l l的线段,去覆盖住尽可能多的点。
一是尽可能把小写字母变成大写,而是尽可能把大写字母变成小写,分2种情况计算。
用DP计算,采用wqs二分即可。

#include
using namespace std;
const int MAX=1e6+10;
const int MOD=998244353;
const int INF=1e9+7;
typedef long long ll;
char s[MAX];
ll n,m,L;
ll sum[MAX];
pair<ll,ll>d[MAX];//d[i]表示i处取最优值以及取最优值时的最小操作次数
ll cal(ll val)
{
    d[0]={0,0};
    for(int i=1;i<=n;i++)
    {
        d[i]=d[i-1];
        d[i].first+=sum[i];
        if(i>L)d[i]=min(d[i],{d[i-L].first+val,d[i-L].second+1});
        else d[i]=min(d[i],{val,1});
    }
    return d[n].second;
}
ll solve(int tag)
{
    for(int i=1;i<=n;i++)sum[i]=tag^('A'<=s[i]&&s[i]<='Z');
    ll l=0,r=n,C=0;
    while(r>=l)
    {
        ll mid=(l+r)/2;
        if(cal(mid)>m)l=mid+1;
        else C=mid,r=mid-1;
    }
    cal(C);
    return d[n].first-C*m;
}
int main()
{
    cin>>n>>m>>L;
    scanf("%s",s+1);
    cout<<min(solve(1),solve(0))<<endl;
    return 0;
}

你可能感兴趣的:(DP)