11
17
2015
0

BZOJ2120-数颜色

分块大法好!块的个数=BLOCK 每块大小=STEP bloans[L][R](1<=L<=R<=BLOCK)表示第L个块至第R个块的答案,每次修改都可以BLOCK^2维护bloans的值,询问时先算出完整的块时的答案 再在两端补上去,可在O(STEP)时间内完成。

这个先自嘲以下数学,BLOCK的大小,我是用N的大小、Q的个数和R的个数算的,理论上的最优值,不过并没有什么卵用

#include <cstdio>
#include <algorithm>
int N,Q,BLOCK,STEP,bloans[400][400],cnt[400][20001],co[10001],q[10001][3],A[20001],v[20001],HASH;
int sqrt3(int x)
{
	int l,r;
	if (x<=1000)
		l=0,r=10;
	else
		if (x<=50000)
			l=11,r=36;
		else
			l=37,r=100;
	while (l<r)
	{
		int m=l+r+1>>1;
		if (m*m*m<=x)
			l=m;
		else
			r=m-1;
	}
	return l;
}
void init()
{
	scanf("%d%d",&N,&Q);
	for (int i=1;i<=N;i++)
		scanf("%d",&co[i]),A[i]=co[i];
	HASH=N;
	int nQ=0,nR=0;
	for (int i=1;i<=Q;i++)
	{
		char c=getchar();
		while (c!='Q'&&c!='R')
			c=getchar();
		q[i][0]=(c=='R');
		scanf("%d%d",&q[i][1],&q[i][2]);
		if (q[i][0])
			A[++HASH]=q[i][2];
	}
	std::sort(A+1,A+HASH+1);
	HASH=std::unique(A+1,A+HASH+1)-A-1;
	for (int i=1;i<=N;i++)
		co[i]=std::lower_bound(A+1,A+HASH+1,co[i])-A;
	for (int i=1;i<=Q;i++)
		if (q[i][0])
			nR++,q[i][2]=std::lower_bound(A+1,A+HASH+1,q[i][2])-A;
		else
			nQ++;
	BLOCK=sqrt3(N*(nQ+1)/(nR+1)/2);
	if (BLOCK>N)
		BLOCK=N;
	if (BLOCK>380)
		BLOCK=380;
	if (BLOCK<1)
		BLOCK=1;
	STEP=N/BLOCK;
	for (int l=1;l<=BLOCK;l++)
	{
		bloans[l][l-1]=0;
		for (int i=1;i<=HASH;i++)
			v[i]=0;
		for (int r=l;r<=BLOCK;r++)
		{
			bloans[l][r]=bloans[l][r-1];
			for (int i=(r-1)*STEP+1;i<=r*STEP;i++)
				if (!v[co[i]])
					v[co[i]]=1,bloans[l][r]++;
		}
	}
	for (int i=1;i<=HASH;i++)
		v[i]=0;
	for (int i=1;i<=BLOCK*STEP;i++)
		cnt[(i+STEP-1)/STEP][co[i]]++;
	for (int i=2;i<=BLOCK;i++)
		for (int j=1;j<=HASH;j++)
			cnt[i][j]+=cnt[i-1][j];
}
void Re(int p,int d)
{
	if (co[p]==d)
		return;
	int IBR=(p+STEP-1)/STEP;
	if (IBR<=BLOCK)
	{
		for (int i=1;i<=IBR;i++)
			for (int j=IBR;j<=BLOCK;j++)
			{
				if (cnt[j][co[p]]-cnt[i-1][co[p]]==1)
					bloans[i][j]--;
				if (cnt[j][d]-cnt[i-1][d]==0)
					bloans[i][j]++;
			}
		for (int i=IBR;i<=BLOCK;i++)
			cnt[i][co[p]]--,cnt[i][d]++;
	}
	co[p]=d;
}
int Qu(int ti,int l,int r)
{
	int LBR=(l+STEP+STEP-2)/STEP,RBR=r/STEP,OUT=0;
	if (RBR>BLOCK)
		RBR=BLOCK;
	if (LBR>RBR)
	{
		for (int i=l;i<=r;i++)
			if (v[co[i]]!=ti)
				v[co[i]]=ti,OUT++;
		return OUT;
	}
	else
	{
		OUT=bloans[LBR][RBR];
		for (int i=(LBR-1)*STEP;i>=l;i--)
			if (v[co[i]]!=ti&&cnt[RBR][co[i]]-cnt[LBR-1][co[i]]==0)
				v[co[i]]=ti,OUT++;
		for (int i=RBR*STEP+1;i<=r;i++)
			if (v[co[i]]!=ti&&cnt[RBR][co[i]]-cnt[LBR-1][co[i]]==0)
				v[co[i]]=ti,OUT++;
		return OUT;
	}
}
int main()
{
	init();
	for (int i=1;i<=Q;i++)
		if (q[i][0])
			Re(q[i][1],q[i][2]);
		else
			printf("%d\n",Qu(i,q[i][1],q[i][2]));
	return 0;
}
Category: 未分类 | Tags: | Read Count: 680

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com