当前位置: 首页 > news >正文

P6801 花式围栏

题目传送门

数学、计数类。

题意

\(n\) 个同一底线上宽 \(w\),高 \(h\),给定的相邻矩形中,数出在方格上的任意形状的小矩形的个数。

\(1\leq n\leq 10^5,1\leq w,h \leq 10^9\)

题解

我们规定竖直方向上为高,水平方向上为的宽。

要研究 \(n\) 个,就要先研究一个。

我们考察在一个长为 \(h\) ,高为 \(w\) 的矩形中有多少个小矩形(区分位置)。

首先一个小矩形可以被分解成高和宽相乘,也就是说想求小矩形的个数,可以先求出有多少种 \(1 \times x\) 的矩形, \(x \times 1\) 同理。

显然只有一维的话两个边界就可以确定,选择两条边,即可框出一种可能。方案数是 \(\frac {(x+1)x} {2}\) 种。

由此可知小矩形的个数是 \(\frac {h(h+1)w(w+1)} {4}\) 个。

现在回到题目,要我们求n个矩形种总共有多少个矩形,我们刚才已经求出来了单个矩形里的数量,这是一类,现在我们要求贯穿多个矩形的小矩形个数。

朴素的想法是枚举矩形的左右端分别在哪个矩形上,再枚举高度,显然要取这段区间内最短的高度,设最低的高度为 \(H\) ,左右端分别在 \(l,r\) 矩形上 \((l \neq r)\),因为水平方向上只于
两端矩形宽度有关,于是总数有:

\[\frac {H(H+1)}{2} w_lw_r \]

再枚举左右端点,于是有:

\[ans=\sum_{1\leq l<r\leq n} \frac {H(H+1)}{2} w_lw_r \]

时间复杂度 \(O(n^2)\) ,需要优化。

在优化带有求和的式子时,一种常用的思维方式就是更换枚举对象和拆解贡献,我们发现枚举两端不好优化,并且又注意到 \(H\) 很多时候都是相同且连续的,所以我们可以尝试在 \(H\) 上下功夫。

\(H\) 写出来:

\[H=\min_{i \in [l,r]} h_i \]

我们尝试枚举每一个 \(h_i\) 对答案的贡献,首先要知道在哪些区间 \([l,r]\)\(H\) 取到了 \(h_i\) (显然不可能断开),于是我们想要知道满足要求一个最大的区间 \([L,R]\) ,也就是 \(L,R\) 最多能往外走多少,这显然是一个单调栈可以解决的,预处理出数组 L[i] 和 R[i] 。

有了这些我们可以尝试枚举 \(i\) ,计算 \(h_i\) 对答案的贡献,第一件事要把式子写出来:

\[ans_i=\sum_{l=L[i]}^{i}\sum_{r=i}^{R[i]} \frac{h_i(h_i+1)}{2} w_lw_r \]

提项看看:

\[ans_i=\frac{h_i(h_i+1)}{2} \sum_{l=L[i]}^{i}\sum_{r=i}^{R[i]} w_lw_r \\ =\frac{h_i(h_i+1)}{2} \sum_{l=L[i]}^{i}(w_l\sum_{r=i}^{R[i]} w_r)\\ =\frac{h_i(h_i+1)}{2} (\sum_{r=i}^{R[i]} w_r)(\sum_{l=L[i]}^{i}w_l) \]

到这里就豁然开朗了,两个 \(\sum\) 再也不用枚举了,直接前缀和维护就可以了,计算复杂度 \(O(1)\)

所以答案就是: \(\sum_{i=1}^{n} ans_i\) 啦!

代码

#include <bits/stdc++.h>
#define int long long 
using namespace std;
const int N=1e5+5;
const int mod=1e9+7;
const int inv2=500000004;
const int inv4=250000002;
int n,ans;
int h[N],w[N],sw[N],q[N],t,L[N],R[N];
void pre(){for(int i=1;i<=n;i++){while(t&&h[q[t]]>=h[i]) t--;L[i]=q[t];q[++t]=i;}t=0;for(int i=n;i>=1;i--){while(t&&h[q[t]]>h[i]) t--;if(t==0) R[i]=n+1;else R[i]=q[t];q[++t]=i;}
}
signed main(){ios::sync_with_stdio(false);cin.tie(0); cout.tie(0);cin>>n;for(int i=1;i<=n;i++) cin>>h[i];for(int i=1;i<=n;i++) cin>>w[i],sw[i]=sw[i-1]+w[i];for(int i=1;i<=n;i++) ans=(ans+h[i]*(h[i]+1)%mod*w[i]%mod*(w[i]+1)%mod*inv4%mod)%mod;pre();for(int i=1;i<=n;i++){if(R[i]-L[i]<=2) continue;int wl=(sw[i]-sw[L[i]]+mod)%mod,wr=(sw[R[i]-1]-sw[i-1]+mod)%mod;ans=(ans+h[i]*(h[i]+1)%mod*inv2%mod*wl%mod*wr%mod)%mod;ans=(ans-h[i]*(h[i]+1)%mod*inv2%mod*w[i]%mod*w[i]%mod+mod)%mod;}cout<<ans;return 0;
}
http://www.zskr.cn/news/7218.html

相关文章:

  • ipadװwindowsϵͳshell
  • input 设置只输入数字或其他自定义字符 - 指南
  • 12-factors
  • huggingface 模型权重文件
  • P4147 玉蟾宫(悬线法)
  • 「Java EE开发指南」如何用MyEclipse开发Java EE企业应用程序?(二)
  • TENGJUN防水TYPE-C 16PIN连接器技术解析:从结构设计到认证标准的全面解读 - 实践
  • MMoE学习笔记:利用门控专家网络高效建模多任务关系
  • SpringMVC使用jasypt加密配置文件 - Commissar
  • 基于Python+Vue开发的口腔牙科预约管理系统源码+运行步骤
  • ECT-OS-JiuHuaShan 框架实现元推理,是人类文明的金种子
  • MATLAB实现连续投影算法
  • PS辉光眩光特效插件 BBTools Glow Glare 2 V2.4.3 For Photoshop
  • 深入解析:Model Context Protocol (MCP) 安全风险与攻击方式解析
  • 剑指offer-31、整数中1出现的次数
  • Centos7非LVM根分区容量不足后扩容,对调硬盘挂载/
  • 详细介绍:Vue3》》eslint Prettier husky
  • Java-Spring入门指南(十)纯Java类配备与@Configuration实战
  • TechInsights 拆解:蔚来“亚当(Adam)”超级计算机
  • 一根网线搞定远程运维,GL-RM1PE 深度体验:远程运维、装机、开机一体化的 KVM over IP - 详解
  • 在AI技术快速实现功能的时代,挖掘电子书阅读器新需求成为关键突破点
  • jtag协议处理流程 - 指南
  • 读人形机器人15未来城市
  • 解锁智能检索新境界:CriticGPT 赋能检索模型洞察人类偏好
  • US$39.99 3+1 Button Remote Key for Nissan 315Mhz FCC ID KBRASTU15 10pcs/lot
  • 编译Unity4.3.1f1
  • US$19 Smart Key Fob For Nissan Micra/Juke/Note Renault Alaska 433MHz
  • 【R课堂-电机专栏】为什么提高电机的电压时,转速会随之上升?
  • Java学习第四天
  • 在线咨询(本地实现—跟练)