codeforces1279F. New Year and Handle Change

傳送門

題意:一個長爲n的字符串,含有大寫字母或小寫字母,最多進行k次操作,將長爲l範圍內的字符全部變爲小寫或全部變爲大寫,求min(lower,upper)的最小值,其中lower是小寫字母的數量,upper是大寫字母的數量.n,k,l<=1e6,l<=n

二分+動態規劃.

首先二分枚舉每次操作最少使lower(upper)數量減少y,然後dp轉移,只有在lower(upper)的數量大於等於y時才發生轉移,dp值表示在最少減少y之外額外減少的lower(或upper)的值,最後需要使得操作次數<=k;經過二分得到最小的k值,此時減少後lower的數量即爲答案.

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long long LL;
typedef long double lb;
#define ri register int
const lb PI=3.141592653589793238462643383279;
const ll inf=1000000000000000000ll;
const int N=1000005,M=998244353;
int n,i,k,p,j,l,r,ans;
int s[N],t[N];
long long dp[N];
char c[N];
int check(int y,bool type,bool f)
{
	int i;
	for(i=1;i<=n;++i)
	{
		if(c[i]>='A'&&c[i]<='Z')
			s[i]=type;
		else
			s[i]=type^1;
		s[i]+=s[i-1];
	}
	cout<<y<<endl;
	for(i=1;i<=n;++i)
	{
		dp[i]=max(dp[i-1],(i-p<0?0:dp[i-p]-s[i-p])+s[i]-y);
		if(dp[i-1]>(i-p<0?0:dp[i-p]-s[i-p])+s[i]-y)
			t[i]=t[i-1];
		else
			if(dp[i-1]<(i-p<0?0:dp[i-p]-s[i-p])+s[i]-y)
				t[i]=t[i-p]+1;
			else
				t[i]=min(t[i-1],t[i-p]+1);
		// cout<<dp[i]<<" "<<t[i]<<endl;
	}
	if(f)
	{
		ans=min(1ll*ans,s[n]-dp[n]-k*y);
	}
	return t[n];
}
int main()
{
	scanf("%d %d %d",&n,&k,&p);
	scanf("%s",c+1);
	l=0,r=p;
	ans=n;
	while(l<r)
	{
		int mid=l+r>>1;
		if(check(mid,0,0)<=k)
			r=mid;
		else
			l=mid+1;
	}
	check(l,0,1);
	l=0,r=p;
	while(l<r)
	{
		int mid=l+r>>1;
		if(check(mid,1,0)<=k)
			r=mid;
		else
			l=mid+1;
	}
	check(l,1,1);
	cout<<ans;
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章