Online JudgeProblem SetAuthorsOnline ContestsUser
Web Board
Home Page
F.A.Qs
Statistical Charts
Problems
Submit Problem
Online Status
Prob.ID:
Register
Update your info
Authors ranklist
Current Contest
Past Contests
Scheduled Contests
Award Contest
User ID:
Password:
  Register

雁过留声——扫描+增量

Posted by fanhqme at 2009-12-20 09:55:56 on Problem 3467
我的方法比较土鳖,但绝对管用。

先考虑对于一个颜色,如何有多少个cross
我的方法:记录每个格子向上、下、左、右各有多少个格子颜色与它相同,然后
取最小-1,就是以这个格子为中心的cross个数了。最后,统统相加。

由于颜色数≤100,所以我把颜色分开考虑,存储100个统计信息。

那么如何应对修改呢?
最朴素的想法:重新扫描、统计。其实,可以利用一下修改前的信息的:
不与被修改的格子同行、同列的格子的信息可以保留,
只有被覆盖的颜色和新的颜色的信息需要更新。

然后就是写了。为了不让代码过长,其实有一些技巧的。

关键代码:
void updataL(int c,int i){
	for (int j=0;j<M;j++)
		if (color[i][j]!=c+1)lc[c][i][j]=0;
		else if (!j || color[i][j-1]!=c+1)lc[c][i][j]=1;
		else lc[c][i][j]=lc[c][i][j-1]+1;
	for (int j=M-1;j>=0;j--)
		if (color[i][j]!=c+1)rc[c][i][j]=0;
		else if (j==M-1 || color[i][j+1]!=c+1)rc[c][i][j]=1;
		else rc[c][i][j]=rc[c][i][j+1]+1;
}
void updataL_nc(int c,int i){
	int tmp;
	for (int j=0;j<M;j++)
		if (color[i][j]==c+1){
			tmp=uc[c][i][j];
			if (tmp>lc[c][i][j])tmp=lc[c][i][j];
			if (tmp>rc[c][i][j])tmp=rc[c][i][j];
			if (tmp>dc[c][i][j])tmp=dc[c][i][j];
			if (nc[c][i][j]!=tmp-1){
				cnt[c]+=tmp-1-nc[c][i][j];
				nc[c][i][j]=tmp-1;
			}
		}else cnt[c]-=nc[c][i][j],nc[c][i][j]=0;
}
void updataR(int c,int j){
	for (int i=0;i<N;i++)
		if (color[i][j]!=c+1)uc[c][i][j]=0;
		else if (!i || color[i-1][j]!=c+1)uc[c][i][j]=1;
		else uc[c][i][j]=uc[c][i-1][j]+1;
	for (int i=N-1;i>=0;i--)
		if (color[i][j]!=c+1)dc[c][i][j]=0;
		else if (i==N-1 || color[i+1][j]!=c+1)dc[c][i][j]=1;
		else dc[c][i][j]=dc[c][i+1][j]+1;
}
void updataR_nc(int c,int j){
	int tmp;
	for (int i=0;i<N;i++)
		if (color[i][j]==c+1){
			tmp=uc[c][i][j];
			if (tmp>lc[c][i][j])tmp=lc[c][i][j];
			if (tmp>rc[c][i][j])tmp=rc[c][i][j];
			if (tmp>dc[c][i][j])tmp=dc[c][i][j];
			if (nc[c][i][j]!=tmp-1){
				cnt[c]+=tmp-1-nc[c][i][j];
				nc[c][i][j]=tmp-1;
			}
		}else cnt[c]-=nc[c][i][j],nc[c][i][j]=0;
}
        for (int i=0;i<N;i++)for (int j=0;j<M;j++)scanf("%d",&color[i][j]);
	for (int i=0;i<C;i++)
		for (int j=0;j<N;j++)
			for (int k=0;k<M;k++)
				nc[i][j][k]=0;
	for (int i=0;i<C;i++)cnt[i]=0;
	for (int i=0;i<C;i++)
		for (int j=0;j<N;j++)
			updataL(i,j);
	for (int i=0;i<C;i++)
		for (int j=0;j<M;j++)
			updataR(i,j);
	for (int i=0;i<C;i++)
		for (int j=0;j<N;j++)
			updataL_nc(i,j);

        while (Q--){
		scanf("%s",buf);
		if (buf[0]=='Q'){
			scanf("%d",&x);
			printf("%d\n",cnt[x-1]);
		}else{
			scanf("%d %d %d",&x,&y,&c);x--;y--;
			d=color[x][y];
			color[x][y]=c;
			updataL(d-1,x);updataR(d-1,y);
			updataL_nc(d-1,x);updataR_nc(d-1,y);
			updataL(c-1,x);updataR(c-1,y);
			updataL_nc(c-1,x);updataR_nc(c-1,y);
		}
	}

Followed by:

Post your reply here:
User ID:
Password:
Title:

Content:

Home Page   Go Back  To top


All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator