P2216 [HAOI2007]理想的正方形题解

一句话总结:二维滑动窗口

看到题目,首先打开标签,看到一个 R M Q RMQ RMQ

第一反应:二维树状数组!

然鹅我并不会二维维护最大最小值。。

第二反应:二维线段树!!

然鹅会超时(实测)(其实是写的太丑了

第三反应:二维st表!

可行!

但是转眼一看,标签里面还有个单调队列

emmm…(回忆起了一道题

于是就有了我们的一句话总结:二维滑动窗口

//单调队列板子
register int head=1,tail=0;
for(int i=1;i<=n;i++){//最大
    while(head<=tail&&q[tail]>=a[i]) --tail;
    q[++tail]=a[i];
    pos[tail]=i;
    if(pos[head]<=i-m) ++head;
    if(i>=m) write(q[head]),putchar(' ');
}
putchar('\n');

head=1,tail=0;
for(int i=1;i<=n;i++){//最小
    while(head<=tail&&q[tail]<=a[i]) --tail;
    q[++tail]=a[i];
    pos[tail]=i;
    if(pos[head]<=i-m) ++head;
    if(i>=m) write(q[head]),putchar(' ');
}
putchar('\n');

然鹅问题又出来了,等我去翻滑动窗口的记录时,我发现自己是用线段树氵过的。。。(于是就重新学了一遍

分析:

滑动窗口是在一条直线上,只用一维维护;

而本题需要找二维的正方形,听起来似乎不难,而且实际上也是如此。

我们需要找到一个办法可以把每个 n × n n×n n×n的正方形中的最大值和最小值维护起来;

而第一反应当然就是对行维护一个最大一个最小,再对列维护一个最大一个最小

这样似乎可行,但是怎么统计答案呢?

因为每个行和列数组的最大最小值不一定代表这个正方形的最大和最小

所以在这停顿,换个想法:对行数组再进行一次单调对列!

这个方法明显可行!因为对行数组在纵方向上再进行一次统计,覆盖的范围就变成二维的了

最后统计答案最大数组 n n n a a a行, n n n b b b列减去答案最小数组对应位置的最小值即可

具体代码

#include<bits/stdc++.h>
#define N 3005
#define inf 0x3f3f3f3f
#define endl '\a'
using namespace std;
int a,b,n,ans=inf;//行数,列数,正方形边长、答案
int mp[N][N];//原数组
int maxn[N][N],minn[N][N];//对每一行处理后的最大最小(以及省空间也拿来当作答案数组了)
int q[N],pos[N]<
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值