BZOJ4384: [POI2015]Trzy wieże

题目大意:要选一段最长的字符串,使得三种字符出现次数各不相同或只有一种

只有一种的直接就能扫出来,然后就想各不相同的

首先维护一个前缀和,代表到每个点时,前缀B,C,S的个数

然后令xi=bi-ci,yi=ci-si,zi=si-bi,每个点权值为自己的位置

如果两个点的xi,yi,zi均不相同,这一段就可以选

所以可以先按x排序,这样就干掉一维

然后我们设x相同的为一组,首先我们把包含权值为1的那一组提到最前面,包含权值为n的那组提到第二组的位置

然后维护6个树状数组

前三个维护最小值,分别代表y值与位置为1的y值相同而z值不同的最小值,以及z相同y不相同的,yz都不相同的

           查询的时候,如果他的yz都跟位置为1的不相同,那最小值直接就是1

          否则根据他的yz来决定去哪组查询最小值

后三个与这个同理,维护最大值

然后具体方式就是,对于每一组,先把这一组的都查询完,然后再插入

这时列一个表格可以发现,还是有一种情况没考虑到,就是最大值在第一组而最小值在第二组的情况,特殊处理一下就好了

神烦的代码,6800B+,除了树状数组基本啥也没有.....

61000msAC,吓尿我,估计如果我TLE了就不调了...正解1000B我也不知道是怎么做的


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 1000010
using namespace std;
char s[N];
int n;
struct ppp{int x,y,z,num;}a[N],a1[N],a2[N];
int cnt1,cnt2;
bool cmp1(ppp x,ppp y){return x.x<y.x;}
struct BIT
{
	int c[N<<1];
	void changemx(int x,int v)
	{
		for(;x<=n+N;x+=x&-x)
		c[x]=max(c[x],v);
	}
	void changemn(int x,int v)
	{
	//	cout<<x-N<<'!'<<v<<endl;
		for(;x<=n+N;x+=x&-x)
		c[x]=min(c[x],v);
	}
	int checkmx(int x)
	{
		int ans=0;
		for(;x;x-=x&-x)
		ans=max(c[x],ans);
		return ans;
	}
	int checkmn(int x)
	{
	//	cout<<x-N<<'?';
		int ans=707185547;
		for(;x;x-=x&-x)
		ans=min(ans,c[x]);
	//	cout<<ans<<endl;
		return ans;
	}
};
BIT zy,zz,ny,nz;
int main()
{
	int i,j,k;
	scanf("%d",&n);
	scanf("%s",s+1);
//	//cout<<s+1;return 0;
	for(i=1;i<=n;i++)
	{
		a[i]=a[i-1];
		a[i].num=i;
		if(s[i]=='B') a[i].x++;
		else if(s[i]=='C') a[i].y++;
		else a[i].z++;
	}
	int o,p,q,oo,pp,qq;
	for(i=1;i<=n;i++)
	{
		o=a[i].x;p=a[i].y;q=a[i].z;
		a[i].x=o-p;a[i].y=p-q;a[i].z=q-o;
	//	cout<<a[i].x<<' '<<a[i].y<<' '<<a[i].z<<endl;
	}
	n++;a[n].x=0;a[n].y=0;a[n].z=0;a[n].num=0;
	
	int ans=0;
	o=a[n].x;p=a[n].y;q=a[n].z;
	oo=a[n-1].x;pp=a[n-1].y;qq=a[n-1].z;
	//cout<<n;
	sort(a+1,a+n+1,cmp1);
	int s1,t1,s2,t2;
	{
		i=1;
		while(a[i].x!=o) i++;
		j=i;
		while(a[j+1].x==a[i].x&&j<n) j++;
		s1=i;t1=j;
		for(k=i;k<=j;k++) cnt1++,a1[cnt1]=a[k];
		i=1;
		while(a[i].x!=oo) i++;
		j=i;
		while(a[j+1].x==a[i].x&&j<n) j++;
		s2=i;t2=j;
		for(k=i;k<=j;k++) cnt2++,a2[cnt2]=a[k];
	//	cout<<s1<<' '<<t1<<' '<<s2<<' '<<t2<<endl;
		if(s1!=s2)
		{
			int e=max(t1,t2);j=e;
			for(i=e;i>cnt1+cnt2;i--)
			{
				while((j>=s1&&j<=t1)||(j>=s2&&j<=t2)) j--;
			//	cout<<j;
				a[i]=a[j];j--;
			}
			for(i=1;i<=cnt1;i++)
			a[i]=a1[i];
			for(i=1;i<=cnt2;i++)
			a[i+cnt1]=a2[i];
			{
	/*puts("");
	for(k=1;k<=n;k++)
		cout<<a[k].x<<' '<<a[k].y<<' '<<a[k].z<<' '<<a[k].num<<endl;*/
				int maxn=-1,p3,qqq;
				for(k=1;k<=cnt1;k++)
				{
					if(a[k].num>maxn)
					maxn=a[k].num,p3=a[k].y,qqq=a[k].z;
				}
			//	cout<<maxn;
				for(k=1;k<=cnt1;k++)
				{
					if(a[k].y!=p3)
					{
						zy.changemx(a[k].z+N,a[k].num);
						ny.changemx(N+1-a[k].z,a[k].num);
					}
					if(a[k].z!=qqq)
					{
						zz.changemx(a[k].y+N,a[k].num);
						nz.changemx(N+1-a[k].y,a[k].num);
					}
				}
					//cout<<' '<<p3<<' '<<qqq<<endl;
				for(k=cnt1+1;k<=cnt2+cnt1;k++)
				{
					if(a[k].y==p3)
					{
						ans=max(ans,zy.checkmx(a[k].z+N-1)-a[k].num+1);
						ans=max(ans,ny.checkmx(N-a[k].z)-a[k].num+1);
						if(a[k].z==qqq)
						{
							ans=max(ans,zz.checkmx(a[k].y+N-1)-a[k].num+1);
							ans=max(ans,nz.checkmx(N-a[k].y)-a[k].num+1);
						}
					}
					else
					{
						if(a[k].z==qqq)
						{
						//	cout<<ans<<'!';
							ans=max(ans,zz.checkmx(a[k].y+N-1)-a[k].num+1);
							ans=max(ans,nz.checkmx(N-a[k].y)-a[k].num+1);
						//	cout<<ans<<endl;
						}
						else ans=max(ans,maxn-a[k].num+1);
					}
					//cout<<ans;
				}
			}
		}
		else
		{
			int e=t1;j=e;
			for(i=e;i>cnt1;i--)
			{
				while(j>=s1&&j<=t1) j--;
				a[i]=a[j];j--;
			}
			for(i=1;i<=cnt1;i++)
			a[i]=a1[i];
		}
	}
		
	memset(zy.c,0,sizeof(zy.c));
	memset(zz.c,0,sizeof(zz.c));
	memset(ny.c,0,sizeof(ny.c));
	memset(nz.c,0,sizeof(nz.c));
	i=1;
	while(a[i].x!=oo) i++;
	j=i;
	while(a[j+1].x==a[i].x&&j<n) j++;
	for(k=i;k<=j;k++)
	{
	//	//cout<<k<<' ';
		if(a[k].y!=pp)
		{
			//cout<<k<<a[k].z;
			zy.changemx(a[k].z+N,a[k].num);
			ny.changemx(N+1-a[k].z,a[k].num);
		}
		if(a[k].z!=qq)
		{
			zz.changemx(a[k].y+N,a[k].num);
			nz.changemx(N+1-a[k].y,a[k].num);
		}
	}
	i=1;
	while(i<=n)
	{
		j=i;
		while(a[j+1].x==a[i].x&&j<n) j++;
		if(a[i].x==oo){i=j+1;continue;}
		for(k=i;k<=j;k++)
		{
			if(a[k].y==pp)
			{
				ans=max(ans,zy.checkmx(a[k].z+N-1)-a[k].num+1);
				ans=max(ans,ny.checkmx(N-a[k].z)-a[k].num+1);
				if(a[k].z==qq)
				{
					ans=max(ans,zz.checkmx(a[k].y+N-1)-a[k].num+1);
					ans=max(ans,nz.checkmx(N-a[k].y)-a[k].num+1);
				}
			}
			else
			{
				if(a[k].z==qq)
				{
					ans=max(ans,zz.checkmx(a[k].y+N-1)-a[k].num+1);
					ans=max(ans,nz.checkmx(N-a[k].y)-a[k].num+1);
				}
				else ans=max(ans,n-a[k].num);
			}
		}
		for(k=i;k<=j;k++)
		{
			if(a[k].y!=pp)
			{
			//	//cout<<k<<a[k].z;
				zy.changemx(a[k].z+N,a[k].num);
				ny.changemx(N+1-a[k].z,a[k].num);
			}
			if(a[k].z!=qq)
			{
				zz.changemx(a[k].y+N,a[k].num);
				nz.changemx(N+1-a[k].y,a[k].num);
			}
		}
		i=j+1;
	}
	//cout<<endl;
	
	memset(zy.c,0x3f,sizeof(zy.c));
	memset(zz.c,0x3f,sizeof(zz.c));
	memset(ny.c,0x3f,sizeof(ny.c));
	memset(nz.c,0x3f,sizeof(nz.c));
	i=1;
	while(a[i].x!=o) i++;
	j=i;
	while(a[j+1].x==a[i].x) j++;
	for(k=i;k<=j;k++)
	{
		if(a[k].y!=p)
		{
			zy.changemn(a[k].z+N,a[k].num);
			ny.changemn(N+1-a[k].z,a[k].num);
		}
		if(a[k].z!=q)
		{
			zz.changemn(a[k].y+N,a[k].num);
			nz.changemn(N+1-a[k].y,a[k].num);
		}
	}
	i=1;
	while(i<=n)
	{
		j=i;
		while(a[j+1].x==a[i].x&&j<n) j++;
		if(a[i].x==o){i=j+1;continue;}
		for(k=i;k<=j;k++)
		{
			if(a[k].y==p)
			{
				ans=max(ans,a[k].num-zy.checkmn(a[k].z+N-1)+1);
				ans=max(ans,a[k].num-ny.checkmn(N-a[k].z)+1);
				if(a[k].z==q)
				{
					ans=max(ans,a[k].num-zz.checkmn(a[k].y+N-1)+1);
					ans=max(ans,a[k].num-nz.checkmn(N-a[k].y)+1);
				}
			}
			else
			{
				if(a[k].z==q)
				{
					ans=max(ans,a[k].num-zz.checkmn(a[k].y+N-1)+1);
					ans=max(ans,a[k].num-nz.checkmn(N-a[k].y)+1);
				}
				else ans=max(ans,a[k].num+1);
			}
		}
		for(k=i;k<=j;k++)
		{
			if(a[k].y!=p)
			{
				zy.changemn(a[k].z+N,a[k].num);
				ny.changemn(N+1-a[k].z,a[k].num);
			}
			if(a[k].z!=q)
			{
				zz.changemn(a[k].y+N,a[k].num);
				nz.changemn(N+1-a[k].y,a[k].num);
			}
		}
		i=j+1;
	}
	ans--;
	int tot=0;
	char now='7';
	for(i=1;i<n;i++)
	{
		if(s[i]==now) tot++;
		else
		{
			ans=max(ans,tot);
			tot=1;
			now=s[i];
		}
	}
	ans=max(ans,tot);
	printf("%d",ans);
}

你可能感兴趣的:(poi,树状数组,bzoj)