专栏文章

CF1279F New Year and Handle Change 题解

CF1279F题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@mipleium
此快照首次捕获于
2025/12/03 13:54
3 个月前
此快照最后确认于
2025/12/03 13:54
3 个月前
查看原文

前置知识

WQS 二分

解法

不妨将大/小写分开做,分别计算大/小写字符的最小值后然后取 min\min,本质是在取若干个区间令其贡献为 00,转移方程比较板。
因具有凸性,故可以使用 WQS 二分求解。

代码

CPP
#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define ull unsigned long long
#define sort stable_sort 
#define endl '\n'
const ll inf=1000000000000;
ll a[1000010],b[1000010],f[1000010],g[1000010];
char s[1000010];
bool check(ll n,ll m,ll len,ll mid)
{
    for(ll i=1;i<=n;i++)
    {
        f[i]=f[i-1]+a[i];  g[i]=g[i-1];
        if(i-len>=0)
        {
            if(f[i-len]-mid<f[i])
            {
                f[i]=f[i-len]-mid;  g[i]=g[i-len]+1;
            }
            else  if(f[i-len]-mid==f[i])  g[i]=max(g[i],g[i-len]+1);
        }
    }
    return g[n]>=m;
}
ll solve(ll n,ll m,ll len,ll op)
{
    ll l=-inf,r=inf,ans=0,mid;
    for(ll i=1;i<=n;i++)  a[i]=('a'<=s[i]&&s[i]<='z')^op;
    while(l<=r)
    {
        mid=(l+r)/2;
        if(check(n,m,len,mid)==true)
        {
            ans=mid;
            r=mid-1;
        }
        else  l=mid+1;
    }
    check(n,m,len,ans);
    return f[n]+ans*m;
}
int main()
{
// #define Isaac
#ifdef Isaac
    freopen("in.in","r",stdin);
    freopen("out.out","w",stdout);
#endif
    ll n,m,len;
    cin>>n>>m>>len;  scanf("%s",s+1);
    cout<<((m*len>=n)?0:min(solve(n,m,len,0),solve(n,m,len,1)))<<endl;
    return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...