luogu P5300 [GXOI/GZOI2019]与或和

Posted 275307894a

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu P5300 [GXOI/GZOI2019]与或和相关的知识,希望对你有一定的参考价值。

题面传送门
一眼看数据范围感觉像一只log
然后因为是位运算所以考虑分开拆位考虑。
分开后就是求矩阵内全\\(0\\)与全\\(1\\)的个数。
然后这个东西其实是单调栈经典问题,就是在单调栈预处理离当前向上距离最近的那个然后直接转移,中间那一段随便转移即可。
时间复杂度\\(O(n^2logw)\\)
code:

#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<cmath>
#include<algorithm>
#include<bitset>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define l(x) x<<1
#define r(x) x<<1|1
#define re register
#define ll long long
#define db double
#define S 10000000
#define N 1000
#define eps (1e-6)
#define mod 1000000007
using namespace std;
int n,m,a[N+5][N+5],f[N+5],g[N+5],st[N+5],head;ll ans1,ans2,tot,pus,dp[N+5];
int main(){
	freopen("1.in","r",stdin);
	re int i,j,k;scanf("%d",&n);for(i=1;i<=n;i++) for(j=1;j<=n;j++) scanf("%d",&a[i][j]);
	for(i=1;i<=n;i++) tot=(tot+n*(n+1)/2*(i))%mod;
	for(k=0;k<=30;k++){
		for(memset(f,0,sizeof(f)),pus=0,i=1;i<=n;i++){
			for(j=1;j<=n;j++)(a[i][j]>>k&1)?(f[j]++):(f[j]=0);
			for(head=0,j=1;j<=n;j++) {
				while(head&&f[st[head]]>f[j]) head--;
				pus+=(dp[j]=(dp[st[head]]+(j-st[head])*f[j])%mod);st[++head]=j;
			}
			pus%=mod;
		}
		ans1+=pus*(1<<k)%mod;
		for(memset(f,0,sizeof(f)),pus=0,i=1;i<=n;i++){
			for(j=1;j<=n;j++)(a[i][j]>>k&1)?(f[j]=0):(f[j]++);
			for(head=0,j=1;j<=n;j++) {
				while(head&&f[st[head]]>f[j]) head--;
				pus+=(dp[j]=(dp[st[head]]+(j-st[head])*f[j])%mod);st[++head]=j;
			}
			pus%=mod;
		}
		ans2+=(tot-pus+mod)*(1<<k)%mod;
	}
	printf("%lld %lld\\n",ans1%mod,ans2%mod);
} 

以上是关于luogu P5300 [GXOI/GZOI2019]与或和的主要内容,如果未能解决你的问题,请参考以下文章

Luogu P5304 [GXOI/GZOI2019]旅行者

Luogu P5304 [GXOI/GZOI2019]旅行者

[LuoguP5305][GXOI/GZOI2019]旧词 (树链剖分)

Loj #3085. 「GXOI / GZOI2019」特技飞行

[GXOI/GZOI2019旅行者]

[GXOI/GZOI2019]与或和