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


    题目传送门

    分析:
    我们考虑求最终交集恰好为某个矩形的答案
    发现这玩意不好求,我们退而求其次
    求最终交集包含某个矩形的答案
    这个就可以做了,考虑一个全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
    ",(ans+MOD)%MOD);
    }
    

  • 相关阅读:
    weui-switch开关控件,表单提交后如何取值
    [转]判断存储过程、触发器、视图是否存在并删除
    修改服务器的3389端口
    如何在react-native 中优雅的使用 redux
    react native js 与 native 的通信与交互方式
    对 JS virtual DOM 的一知半解
    Python的实例方法,类方法,静态方法之间的区别及调用关系
    redux 管理你的 react 应用
    react- native 入门
    git 指南
  • 原文地址:https://www.cnblogs.com/Darknesses/p/13110283.html
Copyright © 2020-2023  润新知