3.29省选模拟赛 矩形

Posted chdy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了3.29省选模拟赛 矩形相关的知识,希望对你有一定的参考价值。

LINK:矩形

一个大小为n的01方阵 m次询问 每次询问求出大小为a行b列的合法矩形的个数.

一个矩阵合法当且仅当其边缘都是为1.

(n,mleq 1500) 2s,256mb

考虑暴力 预处理出 r[i][j],d[i][j] 分别表示向右向下延伸的最长长度。

求答案的时候 枚举每个点 判断一下即可。

考试的时候写了一个一维的st表 和 单调队列做了这个判断。

两种方法时间复杂度一样 n^2m.

考虑优化 从第一种方法中我们考虑采用bitset来优化.

b[i][j][k]表示长度>=i 第j行 第k个位置向右延伸是否可行。

c则维护向下延伸是否可行。这样 我们在每次询问的时候枚举行 然后利用c数组和b数据进行判断即可。

不过维护c数组和b数组 时间复杂度为 n^3/w 空间复杂度也同样如此 计算一下空间 800多mb GG。

考虑分块或者莫队。 这里考虑莫队。

因为我们只要优化一下空间即可。 每次不需要维护那么多的b数组和c数组。

对于b数组我们维护sqrt(n)个 莫队的时候 这个部分更新是n^2的 传递答案是 n^3/w的。

考虑 第二维 发现c的第一维完全没用 所以直接扔了 内部c的更新是n^2的 没有传递答案 所以这样做复杂度为sqrt(n)n^2.

综上发现空间变成了 sqrt(n) * n * n/32的。

可以时间多了一个n^{2.5}次方 可以通过此题。

值得一提的是 我在写的时候迷了半天不知道该怎么写 首先 明确莫队。

莫队的第二维我写的时候也维护了一个sqrt(S) 没发现这个是不必要的 第二维单调递增。

总时间复杂度 n^3 /w +n^2 m/ w+ n^{2.5}.

const int MAXN=1510;
int n,m,B;
bitset<MAXN>b[101][MAXN],c[MAXN],cc;
char a[MAXN][MAXN];
int ans[MAXN],R[MAXN][MAXN],D[MAXN][MAXN];//分别表示向右最长延伸和向下最长延伸.
vector<pii>g[MAXN][2];
struct wy{int x,y,id;}t[MAXN];
inline int cmp(wy a,wy b){return (a.y-1)/B==(b.y-1)/B?a.x<b.x:(a.y-1)/B<(b.y-1)/B;}
inline void gx3(int op,int x,int y)
{
	if(y>n)return;
	if(!g[y-1][op].size())return;
	rep(0,g[y-1][op].size()-1,i)b[x][g[y-1][op][i].F][g[y-1][op][i].S]=0;
}
inline void gx1(int x,int y)//b bitset由x块更新到y块.
{
	while(x<y)
	{
		int st=x*B;
		rep(1,B-1,i)
		{
			gx3(0,B,st+1),++st;
			rep(1,n,j)b[i][j]=b[B][j];
		}
		gx3(0,B,st+1);++x;
	}
}
inline void gx4(int op,int y)
{
	if(y>n)return;
	if(!g[y-1][op].size())return;
	rep(0,g[y-1][op].size()-1,i)c[g[y-1][op][i].F][g[y-1][op][i].S]=0;
}
inline void gx2(int x,int y)
{
	rep(x+1,y,i)gx4(1,i);
}
int main()
{
	freopen("1.in","r",stdin);
	gt(n);gt(m);B=(int)sqrt(n*1.0);
	rep(1,n,i){gc(a[i]),cc[i]=1;}
	rep(1,n,i)
	{
		fep(n,1,j)
		{
			if(a[i][j]==‘0‘)R[i][j]=0;
			else R[i][j]=R[i][j+1]+1;
			if(a[j][i]==‘0‘)D[j][i]=0;
			else D[j][i]=D[j+1][i]+1;
			g[R[i][j]][0].pb(mk(i,j));
			g[D[j][i]][1].pb(mk(j,i));
		}
	}
	rep(1,m,i)
	{
		int x;gt(x);int y;gt(y);
		t[i]=(wy){x,y,i};
	}
	sort(t+1,t+1+m,cmp);
	int wl=0,wr=0;
	rep(1,n,i)b[B][i]=cc;
	for(int i=1;i<=m;++i)
	{
		if(wl*B<t[i].y)
		{
			wr=0;
			rep(1,n,j)c[j]=cc;
			int ww=(t[i].y-1)/B+1;
			gx1(wl,ww);wl=ww;
		}
		while(wr<t[i].x){gx2(wr,t[i].x);wr=t[i].x;}
		int ww=0;
		int s1=t[i].y%B==0?B:t[i].y%B;
		int s2=t[i].x%B==0?B:t[i].x%B;
		int x=t[i].x,y=t[i].y;//x行y列
		rep(1,n-x+1,j)ww=ww+(b[s1][j]&b[s1][j+x-1]&c[j]&(c[j]>>(y-1))).count();
		/*{
			{rep(1,n,k)cout<<c[s2][j][k];cout<<endl;}
			cout<<y-1<<endl;
			cout<<((c[s2][j]>>(y-1)).count())<<endl;
		}*/
		//bitset<MAXN>ss;
		//rep(1,n,j){rep(1,n,k)cout<<b[s1][j][k];cout<<endl;}
		//rep(1,n,j){rep(1,n,k)cout<<c[s2][j][k];cout<<endl;}
		//rep(1,n,j){ss=(c[s2][j]>>(y-1));rep(1,n,k)cout<<ss[k];cout<<endl;}
		ans[t[i].id]=ww;
	}
	rep(1,m,i)put(ans[i]);
	return 0;
}

最后 bitset的空间:一个空间一bit. 一般w=32或64.

bitset的排列是从高位到地位排的所以判断的时候是右移而不是左移。

以上是关于3.29省选模拟赛 矩形的主要内容,如果未能解决你的问题,请参考以下文章

3.29省选模拟赛 除法与取模 dp+组合计数

3.29模拟赛总结

省选联考 2023 同步赛

5.10 省选模拟赛 拍卖 博弈 dp

5.10 省选模拟赛 拍卖 博弈 dp

[考试反思]0410省选模拟67:迷惑