G - Longest Y(二分&思维)

把所有 Y Y Y的下标递增得到一个序列 A A A

然后 B i = A i − i B_i=A_i-i Bi=Aii

问题转化求 B B B中最大连续的相同的数,通过 ± 1 \pm1 ±1的操作。

思考这样的正确性:

A i − i A_i-i Aii表示这个数从 A i A_i Ai移动到位置 i i i需要操作的次数。

如果目标值全部相同说明是在连续的位置,比如目标值为0,则说明在 [ 1 , m ] [1,m] [1,m]

目标值都为 1 1 1,说明在 [ 2 , m + 1 ] [2,m+1] [2,m+1]都为1,可以理解为都移动到0也就是 [ 1 , m ] [1,m] [1,m],然后整体右移一个单位,这样目标值都是 1 1 1了。

答案具有二分性。

对于二分的答案 x x x。显然对于一个区间 x x x,求 min ⁡ ( ∑ l l + x − 1 ∣ B i − y ∣ ) \min(\sum_{l}^{l+x-1}|B_i-y|) min(ll+x1Biy)

显然 y = B l + r 2 y=B_{\tiny\dfrac{l+r}{2}} y=B2l+r,也就是取中点是最优的。

为方便计算贡献,预处理下前缀和即可。

时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)

// Problem: G - Longest Y
// Contest: AtCoder - NEC Programming Contest 2021(AtCoder Beginner Contest 229)
// URL: https://atcoder.jp/contests/abc229/tasks/abc229_g
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// Date: 2021-12-18 15:04:22
// --------by Herio--------

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=2e5+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
const int hashmod[4] = {402653189,805306457,1610612741,998244353};
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define x first
#define y second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
#define IOS ios::sync_with_stdio(false),cin.tie(nullptr)
void Print(int *a,int n){
for(int i=1;i<n;i++)
printf("%d ",a[i]);
printf("%d\n",a[n]);
}
template <typename T> //x=max(x,y) x=min(x,y)
void cmx(T &x,T y){
if(x<y) x=y;
}
template <typename T>
void cmn(T &x,T y){
if(x>y) x=y;
}
int n,m;
ll k;
int a[N];
ll b[N];
char s[N];
bool ck(int x){
int s=0;
rep(i,x,m){
int l=i-x+1;
int mid = l+i>>1;
if(k >= b[i]-b[mid]-a[mid]*(i-mid)+a[mid]*(mid-l)-(b[mid-1]-b[l-1]))
return true;
}
return false;
}
int main(){
scanf("%s",s+1);
n=strlen(s+1);
scanf("%lld",&k);
rep(i,1,n)
if(s[i]=='Y'){
m++;
a[m] = i - m;
b[m] = b[m-1] + a[m];
}
int l=0,r=m,ans=0;
while(l<=r){
int mid=l+r>>1;
if(ck(mid)) ans=mid,l=mid+1;
else r=mid-1;
}
printf("%d\n",ans);
return 0;
}