CF1550E - Stringforces - binary answer, shape pressure DP

Posted by DataRater on Sun, 16 Jan 2022 19:44:58 +0100

E - Stringforces

Title Description

Give you a include? And before k k k lowercase strings s s s. You need to put each? Replace with previous k k One of the k lowercase letters that makes the string s s s v a l val val max.

definition f i f_i fi represents a string s s The longest quanyoudi in s i i The length of a substring of i letters,
v a l = min ⁡ 1 ≤ i ≤ k f i val=\min_{1\le i\le k}f_i val=1≤i≤kmin​fi​
Data range and tips

1 ≤ n ≤ 2 ⋅ 1 0 5 , 1 ≤ k ≤ 17 1\le n\le 2\cdot 10^5,1\le k\le 17 1≤n≤2⋅105,1≤k≤17 .

preface

This problem thought of dichotomy and shape pressure and ran to do F. unexpectedly, he slipped past the front door of the positive solution.

thinking

Take a look at this question k ≤ 17 k\le 17 k ≤ 17, immediately think of state compression.

Because the length of the substring is uncertain, and there are fetches at the same time max ⁡ \max max sum min ⁡ \min min, it's not easy to think directly, but obviously if v a l val val can't get it a a a. Then you can't get it a + 1 a+1 a+1 satisfies monotonicity, so consider the dichotomous answer.

After two answers, v a l val val is sure, that is, the smallest f i f_i fi , determined, which is equivalent to meeting all requirements f i f_i fi , must be greater than or equal to v a l val val . f i f_i fi is greater than or equal to v a l val val if and only if s s There is a with length in s v a l val Quan Youdi of val i i i characters, so we turn the problem into each character i i i find a length of v a l val The interval of val, which satisfies that all characters in the interval can be the second i i i characters, and this k k k intervals do not intersect each other.

Then you can c h e c k check check internal pressure DP: d p [ x ] dp[x] dp[x] indicates that the status of the character type that has solved the demand is x x x, the minimum value of the rightmost endpoint between the selected areas. Then take a O ( n k ) O(nk) O(nk) time preprocessing c l cl cl array, where c l [ i ] [ j ] cl[i][j] cl[i][j] indicates location i i i back, can be the second j j The left end point of the nearest interval selected by j characters, (let the character number start from 0) then transfer to
d p [ x ] = min ⁡ ( 1 < < i ) ∈ x c l [ d p [ x − ( 1 < < i ) ] + 1 ] [ i ] + v a l − 1 dp[x]=\min_{(1<<i)\in x}cl[dp[x-(1<<i)]+1][i]+val-1 dp[x]=(1<<i)∈xmin​cl[dp[x−(1<<i)]+1][i]+val−1
The total transfer complexity is O ( k ⋅ 2 k ) O(k\cdot 2^k) O(k ⋅ 2k), so the total complexity is O ( k log ⁡ n ⋅ ( 2 k + n ) ) O(k\log n\cdot(2^k+n)) O(klogn⋅(2k+n)) .

There is no better way on CF, which is the fastest way. It is worth noting that I actually saw the complexity of up to on CF O ( k log ⁡ n ⋅ 2 k ⋅ k 2 ⋅ log ⁡ n ) O(k\log n\cdot 2^k\cdot \frac{k}{2}\cdot\log n) The AC code of O(klogn ⋅ 2k ⋅ 2k ⋅ logn) shows that the data of this problem is very friendly.

code

171ms rank1 code

#include<cstdio>//JZM yyds!!!
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<ctime>
#include<map>
#define ll long long
#define MAXN 200005
#define MAXM 1000005
#define uns unsigned
#define INF 1e18
#define MOD 1000000007ll
#define lowbit(x) ((x)&(-(x)))
using namespace std;
inline ll read(){
	ll x=0;bool f=1;char s=getchar();
	while((s<'0'||s>'9')&&s>0){if(s=='-')f^=1;s=getchar();}
	while(s>='0'&&s<='9')x=(x<<1)+(x<<3)+s-'0',s=getchar();
	return f?x:-x;
}
int n,k,num[20],cl[MAXN][20];
int dp[MAXN];
char s[MAXN];
inline bool check(int m){
	for(int i=0;i<k;i++)num[i]=0;
	int tot=0;
	for(int j=0;j<k;j++)cl[n+1][j]=cl[n+2][j]=n+1;
//	printf("%d:\n",m);
	for(int i=n;i>0;i--){
		for(int j=0;j<k;j++)cl[i][j]=cl[i+1][j];
		if(s[i]!='?'){
			int c=s[i]-'a';
			num[c]++;
			if(num[c]==1)tot++;
		}
		if(i+m<=n&&s[i+m]!='?'){
			int c=s[i+m]-'a';
			num[c]--;
			if(num[c]==0)tot--;
		}
//		printf(" %d %d\n",i,tot);
		if(i+m>n+1)continue;
		if(tot==1){
			for(int j=0;j<k;j++)if(num[j]>0)cl[i][j]=i;
		}
		else if(tot==0){
			for(int j=0;j<k;j++)cl[i][j]=i;
		}
	}
//	for(int i=1;i<=n;i++)printf(" %d %d\n",cl[i][0],cl[i][1]);
	int lim=(1<<k);
	for(int s=1;s<lim;s++)dp[s]=n+1;
	dp[0]=0;
	for(int s=1;s<lim;s++)
		for(int i=0;i<k;i++)
			if((s>>i)&1){
				int p=s^(1<<i);
				dp[s]=min(dp[s],cl[dp[p]+1][i]+m-1);
			}
	return dp[lim-1]<=n;
}
signed main()
{
	n=read(),k=read();
	scanf("%s",s+1);
	int l=0,r=n/k,mid;
	while(l<r){
		mid=(l+r+1)>>1;
		if(check(mid))l=mid;
		else r=mid-1;
	}
	printf("%d\n",l);
	return 0;
}

Topics: Algorithm string Binary Search CodeForces