Codeforces Round 938 (Div. 3) E

链接

有点意思的题目。
首先可以得到的一个结论就是,如果k能够完成,那唯一的操作方法就是从前往后,遇到0就使用,把这个点变成1。

那么我们就能够做到O(n)验证了,然后发现O(n^2)可以接受,就过了。

但是我因为滥用数据结构,导致我认为验证需要O(nlogn)然后5000又刚刚好跑不过去。
所以觉得做法假了,尝试从减少验证的次数上下手。
首先可以发现一个性质,就是如果k=m的时候是可以分解完成的,那么m的所有因子作为k也是可以的,
那假如能够证明,所有合法的k都是一个数字的因子的话,那这题就可以通过质因数分解的方法来做到两个log
很明显,不可以。反例:011110 k=5和2都可以。
然后就做法假了。

死因:没有发现滑动窗口是不需要动态维护前缀和的,只需要O(1)即可维护。
这一点记下来,以后还是尽量少用树状数组吧。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read() {
	char c=getchar();int a=0,b=1;
	for(;c<'0'||c>'9';c=getchar())if(c=='-')b=-1;
	for(;c>='0'&&c<='9';c=getchar())a=a*10+c-48;return a*b;
}
int n,a[5001],ans,b[5001];
int main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	int T=read();
	while(T--)
	{
		n=read();
		string s;
		cin>>s;
		for(int i=1;i<=n;i++)
		{
			a[i]=s[i-1]-'0';
		}
		int ans=0;
		for(int i=n;i>=1;i--)
		{
			for(int j=1;j<=n;j++)
			{
				b[j]=0;
			}
			int now=0;
			for(int j=1;j<=n-i+1;j++)
			{
				now+=b[j];
				if((a[j]+now)%2==0)
				{
					b[j]++;
					now++;
					b[j+i]++;
				}
			}
			bool flag=0;
			for(int j=n-i+2;j<=n;j++)
			{
				now+=b[j];
				if((a[j]+now)%2==0)
				{
					flag=1;
					break;
				}
			}
			if(flag==0)
			{
				ans=i;
				break;
			}
		}
		cout<<ans<<endl;
	}
	return 0;
}

upd:2024 4 10
才发现放错代码了。。放成了上一份的代码

posted @ 2024-04-09 17:36  HL_ZZP  阅读(9)  评论(0编辑  收藏  举报