社区讨论

0分求调

P2601[ZJOI2009] 对称的正方形参与者 1已保存回复 0

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
0 条
当前快照
1 份
快照标识符
@mhpi3yhi
此快照首次捕获于
2025/11/08 07:43
3 个月前
此快照最后确认于
2025/11/08 07:43
3 个月前
查看原帖
马拉车写法,和第四篇题解 思路差不多,但建字符串方式不同
CPP
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int maxn=2e3+10;
int a[maxn][maxn],c[maxn][maxn];
int p1[maxn][maxn],p2[maxn][maxn],pp[maxn],lr[maxn][maxn],ud[maxn][maxn];
int lg[maxn];
int f[maxn][13];
long long ans;
int n,m;
inline void solve(int opt,int id,int len,int p[][maxn])
{
	memset(pp,0,sizeof pp);
	int mid=0,r=0;
	for (int i=1;i<len;i++)
	{
		if (pp[i]<=r) pp[i]=min(pp[mid*2-i],r-i+1);
		else pp[i]=1;
		if (opt) while (c[id][i+pp[i]]==c[id][i-pp[i]]) pp[i]++;
		else while (c[i+pp[i]][id]==c[i-pp[i]][id]) pp[i]++;
		if (i+pp[i]-1>r)
		{
			r=i+pp[i]-1;
			mid=i;
		}
	}
	if (opt) for (int i=1;i<len;i++) p[id][i]=pp[i]-1; 
	else for (int i=1;i<len;i++) p[i][id]=pp[i]-1; 
}
inline int query(int l,int r,int len)
{
	if (l<=0||r>=len) return 0;
	int s=r-l+1;
	return min(f[l][lg[s]],f[r-(1<<lg[s])+1][lg[s]]);
}
inline void init_(int len)
{
	for (int j=1;j<=lg[len];j++)
	{
		for (int i=1;i+(1<<j)-1<=len;i++)
		{
			f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
		} 
	}
}
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n>>m;
	lg[1]=0;
	for (int i=2;i<=2040;i++) lg[i]=lg[i>>1]+1;
	for (int i=0;i<n;i++)
		for (int j=0;j<m;j++) 
			cin>>a[i][j];
	for (int i=0;i<=2*n+2;i++) c[i][0]=-1;
	for (int i=0;i<=2*m+2;i++) c[0][i]=-1;
	for (int i=0;i<n;i++)
		for (int j=0;j<m;j++)
			c[i*2+2][j*2+2]=a[i][j];
	for (int i=0;i<=2*n+2;i++) c[i][2*m+2]=-2;
	for (int i=0;i<=2*m+2;i++) c[2*n+2][i]=-2;
	n=2*n+2,m=2*m+2;
	for (int i=1;i<n;i++) solve(1,i,m,p1);
	for (int i=1;i<m;i++) solve(0,i,n,p2);
	for (int i=1;i<n;i++)
	{
		memset(f,0,sizeof f);
		for (int j=1;j<m;j++)
		{
			f[j][0]=p2[i][j];
		}
		init_(m-1);
		for (int j=1;j<m;j++)
		{
			int l=0,r=m;
			while (l<r)
			{
				int mid=(l+r+1)>>1;
				if (query(j-mid+1,j+mid-1,m-1)>=mid) l=mid;
				else r=mid-1;
			}
			lr[i][j]=l;
		}
	}
	for (int i=1;i<m;i++)
	{
		memset(f,0,sizeof f);
		for (int j=1;j<n;j++)
		{
			f[j][0]=p1[j][i];
		}
		init_(n-1);
		for (int j=1;j<n;j++)
		{
			int l=1,r=n;
			while (l<r)
			{
				int mid=(l+r+1)>>1;
				if (query(j-mid+1,j+mid-1,n-1)>=mid) l=mid;
				else r=mid-1;
			}
			ud[j][i]=l;
		}
	}
	for (int i=1;i<n;i++)
	{
		for (int j=1;j<m;j++)
		{
			int x=min(lr[i][j],ud[i][j]);
			if (c[i][j]>0) ans+=(x+1)/2;
			else ans+=x/2;
		}
	}
	cout<<ans<<"\n";
	return 0;
} 

回复

0 条回复,欢迎继续交流。

正在加载回复...