既然选择了远方,便只顾风雨兼行|

H_W_Y

园龄:1年11个月粉丝:28关注:15

2023-10-27 07:56阅读: 27评论: 0推荐: 0

P3400 仓鼠窝 题解-单调栈典题

20231026

P3400 仓鼠窝 题解-单调栈典题

Statement

传送门

输出 01 矩阵中不含 0 的子矩阵的个数。n,m3000

Solution

很妙的做法,典题,于是写了题解。

做法也很简单,就是你枚举每一个节点作为右上角的点的方案数,

发现其实有很多无用的点,比如有一个在你后面且比你高的点,

这样你就被淘汰了。

于是对于那些有用的点,我们可以直接用单调栈维护,

同时维护一个前缀和就是对答案的贡献。

具体实现就是枚举每一行,

再从左往右扫从而计算答案即可。

代码非常短。。。

#include <bits/stdc++.h>
using namespace std;
#define ll long long

const int N=3e3+5;
int n,m,a[N][N],d[N],st[N],tp=0;
ll ans=0,s[N];

int read(){
  int x=0,f=1;char ch=getchar();
  while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
  while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
  return x*f;
}

int main(){
  /*2023.10.26 H_W_Y P3400 仓鼠窝 单调栈*/ 
  n=read();m=read();
  for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) a[i][j]=read();
  for(int i=1;i<=n;i++,tp=0)
    for(int j=1;j<=m;j++){
      if(!a[i][j]) d[j]=i;
      while(tp>0&&d[st[tp]]<d[j]) tp--;
      st[++tp]=j;
      ans+=(s[tp]=s[tp-1]+(i-d[st[tp]])*(st[tp]-st[tp-1])); 
	}
  printf("%lld\n",ans);
  return 0;
}

Conclusion

矩阵个数统计我们可以尝试维护每一个点为右上角的合法矩阵数量。

本文作者:H_W_Y

本文链接:https://www.cnblogs.com/H-W-Y/p/P3400.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   H_W_Y  阅读(27)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起