ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

联考20200612 T1 「雅礼集训 2018 Day11」进攻!

2020-06-12 21:05:43  阅读:294  来源: 互联网

标签:20200612 getint int tp stk 雅礼 include 矩形 联考


题目传送门

分析:
我们考虑求最终交集恰好为某个矩形的答案
发现这玩意不好求,我们退而求其次
求最终交集包含某个矩形的答案
这个就可以做了,考虑一个全1矩形贡献范围为给一个矩形内部+1,差分一下变成两个角+1,两个角-1
差分后的贡献可以转化为一个全1矩形对左上右上左下右下的贡献,这个做四次单调栈DP就好了
一个\(n*m\)的矩形会被他内部:
\(1*1\)的矩形算\(n*m\)次
\(1*2\)的矩形算\(n*(m-1)\)次
\(2*1\)的矩形算\((n-1)*m\)次
\(2*2\)的矩形算\((n-1)*(m-1)\)次
发现\(n*m+(n-1)*(m-1)-n*(m-1)-(n-1)*m=1\)这个矩形就只被算一次了
于是我们求最终交集包含的矩形的答案,只需要求得大小为\(1*1,1*2,2*1,2*2\)的矩形的答案就好了
复杂度\(O(n^2logK)\)

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
#include<queue>
#include<map>

#define maxn 2005
#define INF 0x3f3f3f3f
#define MOD 998244353

using namespace std;

inline int getint()
{
	int num=0,flag=1;char c;
	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
	while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
	return num*flag;
}

int n,m,K;
char s[maxn][maxn];
long long f[4][maxn][maxn],g[maxn][maxn];
int sum[maxn][maxn];
long long ans;
int stk[maxn],tp;

inline long long ksm(long long num,long long k)
{
	long long ret=1;
	for(;k;k>>=1,num=num*num%MOD)if(k&1)ret=ret*num%MOD;
	return ret;
}

inline void solve()
{
	for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)sum[i][j]=(s[i][j]-48)?sum[i-1][j]+1:0;
	for(int i=1;i<=n;i++)for(int j=1,cnt=tp=0;j<=m;j++)
	{
		while(tp&&sum[i][stk[tp]]>=sum[i][j])cnt-=sum[i][stk[tp]]*(stk[tp]-stk[tp-1]),--tp;
		cnt+=sum[i][j]*(j-stk[tp]);
		g[i][j]=cnt,stk[++tp]=j;
	}
}

int main()
{
	n=getint(),m=getint(),K=getint();
	for(int i=1;i<=n;i++)scanf("%s",s[i]+1);
	
	solve();
	for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
	{
		f[0][i+1][j+1]+=g[i][j];
		f[1][i][j+1]+=g[i][j];
		f[2][i+1][j]+=g[i][j];
		f[3][i][j]+=g[i][j];
	}
	
	for(int i=1;i<=n;i++)reverse(s[i]+1,s[i]+m+1);
	solve();
	for(int i=1;i<=n;i++)reverse(g[i]+1,g[i]+m+1);
	for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
	{
		f[0][i+1][j]-=g[i][j];
		f[1][i][j]-=g[i][j];
		f[2][i+1][j]-=g[i][j];
		f[3][i][j]-=g[i][j];
	}
	
	reverse(s+1,s+n+1);
	solve();
	reverse(g+1,g+n+1);
	for(int i=1;i<=n;i++)reverse(g[i]+1,g[i]+m+1);
	for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
	{
		f[0][i][j]+=g[i][j];
		f[1][i][j]+=g[i][j];
		f[2][i][j]+=g[i][j];
		f[3][i][j]+=g[i][j];
	}
	
	for(int i=1;i<=n;i++)reverse(s[i]+1,s[i]+m+1);
	solve();
	reverse(g+1,g+n+1);
	for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
	{
		f[0][i][j+1]-=g[i][j];
		f[1][i][j+1]-=g[i][j];
		f[2][i][j]-=g[i][j];
		f[3][i][j]-=g[i][j];
	}
	
	for(int k=0;k<4;k++)
		for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
			f[k][i][j]=f[k][i][j]-f[k][i-1][j-1]+f[k][i-1][j]+f[k][i][j-1];
	for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
	{
		ans=(ans+ksm(f[0][i][j]%MOD,K))%MOD;
		ans=(ans-ksm(f[1][i][j]%MOD,K))%MOD;
		ans=(ans-ksm(f[2][i][j]%MOD,K))%MOD;
		ans=(ans+ksm(f[3][i][j]%MOD,K))%MOD;
	}
	printf("%lld\n",(ans+MOD)%MOD);
}

标签:20200612,getint,int,tp,stk,雅礼,include,矩形,联考
来源: https://www.cnblogs.com/Darknesses/p/13110283.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有