zoukankan      html  css  js  c++  java
  • [GXOI/GZOI2019]与或和——单调栈

    题目链接:

    [GXOI/GZOI2019]与或和

    既然求的是二进制运算的和,那么我们按位考虑,这样就将矩阵变成了一个$01$矩阵。

    对于或运算,就是求有多少个子矩形中有$1$。

    直接求不好办,考虑有多少个矩形只有$0$。

    我们统计以每个$0$为矩形右下角的矩形有多少个。

    对于第$i$行的每一列维护出从这一行开始往上有多少个连续的$0$。

    现在问题就变成了对于第$i$行的每一列,之前有多少个格子能作为矩形的左上角和它匹配。

    用单调栈维护一个单调递增的序列对每行分别统计答案即可。

    对于与运算,就是将总子矩形数$-$包含$0$的子矩形数,对$0$再做一遍即可。

    #include<set>
    #include<map>
    #include<queue>
    #include<stack>
    #include<cmath>
    #include<vector>
    #include<bitset>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define ll long long
    #define pr pair<int,int>
    using namespace std;
    const int mod=1e9+7;
    ll ans1,ans2;
    int a[1010][1010];
    int b[1010][1010];
    int n;
    int mx[1010];
    int top;
    pr st[1010];
    ll sum;
    ll find1()
    {
    	memset(mx,0,sizeof(mx));
    	ll res=0;
    	for(int i=1;i<=n;++i)
    	{
    		ll num=0;
    		top=0;
    		for(int j=1;j<=n;++j)
    		{
    			mx[j]=b[i][j]?mx[j]+1:0;
    			int len=1;
    			while(top&&st[top].first>=mx[j])
    			{
    				num-=st[top].first*st[top].second;
    				len+=st[top].second;
    				top--;
    			}
    			num+=mx[j]*len;
    			res=(res+num)%mod;
    			st[++top]=make_pair(mx[j],len);
    		}
    	}
    	return res;
    }
    ll find2()
    {
    	memset(mx,0,sizeof(mx));
    	ll res=0;
    	for(int i=1;i<=n;++i)
    	{
    		ll num=0;
    		top=0;
    		for(int j=1;j<=n;++j)
    		{
    			mx[j]=(!b[i][j])?mx[j]+1:0;
    			int len=1;
    			while(top&&st[top].first>=mx[j])
    			{
    				num-=st[top].first*st[top].second;
    				len+=st[top].second;
    				top--;
    			}
    			num+=mx[j]*len;
    			res=(res+num)%mod;
    			st[++top]=make_pair(mx[j],len);
    		}
    	}
    	return res;
    }
    int main()
    {
    	scanf("%d",&n);
    	sum=1ll*n*(n+1)/2*n*(n+1)/2;
    	sum%=mod;
    	for(int i=1;i<=n;++i)
    	{
    		for(int j=1;j<=n;++j)
    		{
    			scanf("%d",&a[i][j]);
    		}
    	}
    	for(int k=0;k<=31;++k)
    	{
    		for(int i=1;i<=n;++i)
    		{
    			for(int j=1;j<=n;++j)
    			{
    				if(a[i][j]&(1<<k))
    				{
    					b[i][j]=1;
    				}
    				else
    				{
    					b[i][j]=0;
    				}
    			}
    		}
    		ans1+=(1ll<<k)%mod*find1()%mod,ans1%=mod;
    		ans2+=(1ll<<k)%mod*(sum-find2()+mod)%mod,ans2%=mod;
    	}
    	ans1=(ans1%mod+mod)%mod,ans2=(ans2%mod+mod)%mod;
    	printf("%lld %lld",ans1,ans2);
    }
  • 相关阅读:
    Jmeter 02 JMeter体系结构
    从一个实例详解敏捷测试的最佳实践
    BI测试
    A/B测试与灰度发布
    性能测试之稳定性测试(可靠性测试)
    Jmeter 01
    浅谈<持续集成、持续交付、持续部署>(二)
    浅谈<持续集成、持续交付、持续部署>(一)
    Python总结
    Latex技巧:LaTex插图命令includegraphics参数详解
  • 原文地址:https://www.cnblogs.com/Khada-Jhin/p/10716530.html
Copyright © 2011-2022 走看看