news 2026/7/9 15:59:50

单调栈、单调队列(模板)、子矩阵(模板)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
单调栈、单调队列(模板)、子矩阵(模板)

单调栈

问题描述

给定一个长度为 NN的序列 aa

第一行输出每个数字其左边第一个比其的数字,不存在则输出-1

第二行输出每个数字其右边第一个比其的数字,不存在则输出-1

第三行输出每个数字其左边第一个比其的数字,不存在则输出-1

第四行输出每个数字其右边第一个比其的数字,不存在则输出-1

update:本题数据于 2025-01-13 加强至 2×1052×105,以杜绝暴力通过。

输入格式

第一行输入一个正整数 NN。(1≤N≤2×105)(1≤N≤2×105)

第二行输入 NN个正整数,表示序列 aa。(1≤ai≤105,1≤i≤N)(1≤ai​≤105,1≤iN)

输出格式

第一行输出每个数字其左边第一个比其的数字,不存在则输出-1

第二行输出每个数字其右边第一个比其的数字,不存在则输出-1

第三行输出每个数字其左边第一个比其的数字,不存在则输出-1

第四行输出每个数字其右边第一个比其的数字,不存在则输出-1

样例输入

5 4 3 2 1 5

样例输出

-1 4 3 2 -1 5 5 5 5 -1 -1 -1 -1 -1 1 3 2 1 -1 -1
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.util.*; public class Main { static int N=2*100010,mod=998244353; static int a[]=new int[N]; static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); static BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out)); public static void main(String[] args) throws IOException { StringTokenizer st=new StringTokenizer(br.readLine()); int n=Integer.parseInt(st.nextToken()); st=new StringTokenizer(br.readLine()); for (int i = 0; i < n; i++) { a[i]=Integer.parseInt(st.nextToken()); } //输出每个数字其左边第一个比其大的数字 Stack<Integer> stack=new Stack<Integer>();//维护一个单调递减的栈 存 int r1[]=new int[n]; Arrays.fill(r1, -1); for (int i = 0; i < n; i++) { int u=a[i]; while(!stack.isEmpty() && stack.peek()<=u){ stack.pop(); } if(!stack.isEmpty())r1[i]=stack.peek(); stack.add(u); } for (int i = 0; i < n ; i++) { bw.write(r1[i]+" "); } bw.write("\n"); //输出每个数字其右边第一个比其大的数字 Stack<Integer> stack1=new Stack<Integer>();//维护一个单调递减的栈 int r2[]=new int[n]; Arrays.fill(r2, -1); for (int i = n-1; i >=0; i--) { int u=a[i]; while(!stack1.isEmpty() && stack1.peek()<=u){ stack1.pop(); } if(!stack1.isEmpty())r2[i]=stack1.peek(); stack1.add(u); } for (int i = 0; i < n ; i++) { bw.write(r2[i]+" "); } bw.write("\n"); //输出每个数字其左边第一个比其小的数字 Stack<Integer> stack2=new Stack<Integer>();//维护一个单调递增的栈 int r3[]=new int[n]; Arrays.fill(r3, -1); for (int i = 0; i < n; i++) { int u=a[i]; while(!stack2.isEmpty() && stack2.peek()>=u){ stack2.pop(); } if(!stack2.isEmpty())r3[i]=stack2.peek(); stack2.add(u); } for (int i = 0; i < n ; i++) { bw.write(r3[i]+" "); } bw.write("\n"); //输出每个数字其右边第一个比其小的数字 Stack<Integer> stack3=new Stack<Integer>();//维护一个单调递增的栈 int r4[]=new int[n]; Arrays.fill(r4, -1); for (int i = n-1; i >=0; i--) { int u=a[i]; while(!stack3.isEmpty() && stack3.peek()>=u){ stack3.pop(); } if(!stack3.isEmpty())r4[i]=stack3.peek(); stack3.add(u); } for (int i = 0; i < n ; i++) { bw.write(r4[i]+" "); } bw.write("\n"); br.close(); bw.flush(); bw.close(); } }

单调队列(模板)

问题描述

给定一个长度为 NN 的序列 aa 与一个长度为 KK 的窗口。(1≤K≤N)(1≤K≤N)

该窗口会从序列的最左端滑动到最右端,你需要输出 22 行,每行 N−K+1N−K+1 个数字。

第 11 行为每个窗口的最小值。

第 22 行为每个窗口的最大值。

输入格式

第一行输入两个正整数 N,KN,K。(1≤K≤N≤105)(1≤K≤N≤105)

第二行输入 NN 个正整数,表示序列 aa。(1≤ai≤105)(1≤ai​≤105)

输出格式

输出 22 行,每行 N−K+1N−K+1 个数字。

第 11 行为每个窗口的最小值。

第 22 行为每个窗口的最大值。

样例输入

8 3 1 3 1 3 5 3 6 7

样例输出

1 1 1 3 3 3 3 3 5 5 6 7
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.util.*; public class Main { static int N=100010; static int a[]=new int[N]; static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); static BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out)); public static void main(String[] args) throws IOException { StringTokenizer st=new StringTokenizer(br.readLine()); int n=Integer.parseInt(st.nextToken()),k=Integer.parseInt(st.nextToken()); st=new StringTokenizer(br.readLine()); for (int i = 0; i < n; i++) { a[i]=Integer.parseInt(st.nextToken()); } //求每个窗口的最小值 Deque<Integer> deque=new LinkedList<Integer>();//维护一个单调递增的队列 存下标 for (int i = 0; i < n; i++) { int u=a[i]; //清除过期数据 while(!deque.isEmpty() && i-deque.getFirst()>=k)deque.pop(); //维护单调性 while(!deque.isEmpty() && a[deque.getLast()]>=u){ deque.pollLast(); } deque.add(i); if(i>=k-1){//数量不够不可输出 bw.write(a[deque.peekFirst()]+" "); } } bw.write("\n"); //求每个窗口的最大值 Deque<Integer> deque1=new LinkedList<Integer>();//维护一个单调递减的队列 存下标 for (int i = 0; i < n; i++) { int u=a[i]; //清除过期数据 while(!deque1.isEmpty() && i-deque1.getFirst()>=k)deque1.pop(); //维护单调性 while(!deque1.isEmpty() && a[deque1.getLast()]<=u){ deque1.pollLast(); } deque1.add(i); if(i>=k-1){//数量不够不可输出 bw.write(a[deque1.peekFirst()]+" "); } } bw.write("\n"); br.close(); bw.flush(); bw.close(); } }

子矩阵(模板)

问题描述

给定一个 n×mn×m (nn 行 mm 列)的矩阵。设一个

矩阵的价值为其所有数中的最大值和最小值的乘积。求给定矩阵的所有大小为 a×ba×b (aa 行 bb 列)的子矩阵的价值的和。

答案可能很大,你只需要输出答案对 998244353998244353 取模后的结果。

输入格式

输入的第一行包含四个整数分别表示 nn,mm,aa,bb,相邻整数之间使用一个空格分隔。接下来

nn 行每行包含 mm 个整数,相邻整数之间使用一个空格分隔,表示矩阵中的每个数 Ai,jAi,j​。

输出格式

输出一行包含一个整数表示答案。

样例输入

2 3 1 2 1 2 3 4 5 6

样例输出

样例说明

1×2+2×3+4×5+5×6=581×2+2×3+4×5+5×6=58。

评测用例规模与约定

对于 4040% 的评测用例,1≤n,m≤1001≤n,m≤100;

对于 7070% 的评测用例,1≤n,m≤5001≤n,m≤500;

对于所有评测用例,1≤a≤n≤10001≤a≤n≤1000,1≤b≤m≤10001≤b≤m≤1000,1≤Ai,j≤1091≤Ai,j​≤109。

import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.util.*; public class Main { static int N=1010,mod=998244353; static int u[][]=new int[N][N]; static int rowWindowMax[][]=new int[N][N]; static int rowWindowMin[][]=new int[N][N]; static int WindowMax[][]=new int[N][N]; static int WindowMin[][]=new int[N][N]; static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); static BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out)); public static void main(String[] args) throws IOException { StringTokenizer st=new StringTokenizer(br.readLine()); int n=Integer.parseInt(st.nextToken()),m=Integer.parseInt(st.nextToken()); int a=Integer.parseInt(st.nextToken()),b=Integer.parseInt(st.nextToken()); for (int i = 0; i < n; i++) { st=new StringTokenizer(br.readLine()); for (int j = 0; j < m; j++) { u[i][j]=Integer.parseInt(st.nextToken()); } } //求最大值 for (int i = 0; i < n; i++) { //对于每一行 维护一个长度为b的滑动窗口 Deque<Integer> deque=new LinkedList<Integer>(); for (int j = 0; j < m; j++) { int g=u[i][j]; //清除过期数据 while(!deque.isEmpty() && j-deque.peek()>=b)deque.poll(); //维护单调队列 while(!deque.isEmpty() && u[i][deque.getLast()]<=g)deque.pollLast(); deque.add(j); if(!deque.isEmpty())rowWindowMax[i][j]=u[i][deque.peek()]; } } //求最小值 for (int i = 0; i < n; i++) { //对于每一行 维护一个长度为b的滑动窗口 Deque<Integer> deque=new LinkedList<Integer>(); for (int j = 0; j < m; j++) { int g=u[i][j]; //清除过期数据 while(!deque.isEmpty() && j-deque.peek()>=b)deque.poll(); //维护单调队列 while(!deque.isEmpty() && u[i][deque.getLast()]>=g)deque.pollLast(); deque.add(j); if(!deque.isEmpty())rowWindowMin[i][j]=u[i][deque.peek()]; } } for (int i = 0; i < m; i++) { //对于每一列 维护一个长度为a的滑动窗口 Deque<Integer> deque=new LinkedList<Integer>(); for (int j = 0; j < n; j++) { int g=rowWindowMax[j][i]; //清除过期数据 while(!deque.isEmpty() && j-deque.peek()>=a)deque.poll(); //维护单调队列 while(!deque.isEmpty() && rowWindowMax[deque.getLast()][i]<=g)deque.pollLast(); deque.add(j); if(!deque.isEmpty())WindowMax[j][i]=rowWindowMax[deque.peek()][i]; } } for (int i = 0; i < m; i++) { //对于每一列 维护一个长度为a的滑动窗口 Deque<Integer> deque=new LinkedList<Integer>(); for (int j = 0; j < n; j++) { int g=rowWindowMin[j][i]; //清除过期数据 while(!deque.isEmpty() && j-deque.peek()>=a)deque.poll(); //维护单调队列 while(!deque.isEmpty() && rowWindowMin[deque.getLast()][i]>=g)deque.pollLast(); deque.add(j); if(!deque.isEmpty())WindowMin[j][i]=rowWindowMin[deque.peek()][i]; } } long res=0; for (int i = a-1; i < n; i++) { for (int j = b-1; j < m; j++) { res=(res+(long)WindowMax[i][j]*WindowMin[i][j]%mod)%mod; } } bw.write(res+""); br.close(); bw.flush(); bw.close(); } }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/9 15:59:35

如何快速掌握FModel:虚幻引擎游戏资产浏览器的终极指南

如何快速掌握FModel&#xff1a;虚幻引擎游戏资产浏览器的终极指南 【免费下载链接】FModel Unreal Engine Archives Explorer 项目地址: https://gitcode.com/gh_mirrors/fm/FModel 你是否曾经好奇《堡垒之夜》、《无畏契约》等热门游戏中的精美角色模型、炫酷武器皮肤…

作者头像 李华
网站建设 2026/7/9 15:58:59

Dism++系统优化完整指南:从C盘爆满到性能飞跃的终极解决方案

Dism系统优化完整指南&#xff1a;从C盘爆满到性能飞跃的终极解决方案 【免费下载链接】Dism-Multi-language Dism Multi-language Support & BUG Report 项目地址: https://gitcode.com/gh_mirrors/di/Dism-Multi-language 你是否经常遇到C盘突然变红、Windows更新…

作者头像 李华
网站建设 2026/7/9 15:58:28

用Python处理大数据:高效编程技巧分享

当你的Python脚本在处理几百万行数据时突然卡死&#xff0c;内存飙升到90%&#xff0c;你恨不得砸了电脑。别急&#xff0c;我经历过同样的困境&#xff0c;然后找到了解法。大数据处理在Python中从来不是“不能做”&#xff0c;而是“很多人不会做”。实际上&#xff0c;只要掌…

作者头像 李华
网站建设 2026/7/9 15:57:52

SpireCV-Pro 1.0 正式发布:x86 免费、浏览器调试、仿真评测一体

如果你做过无人机、无人车、机器人视觉&#xff0c;可能很熟悉这样的开发日常&#xff1a;算法在电脑上调好了&#xff0c;上板子之后又要重新适配仿真能跑&#xff0c;真实相机一接就开始查链路远程服务器没有桌面&#xff0c;想看一眼画面还得折腾转发模型指标、实时画面、原…

作者头像 李华
网站建设 2026/7/9 15:56:23

C++ WebSocket服务实战:基于WebSocket++与Asio构建高性能实时通信后端

1. 项目概述与核心价值 最近在做一个需要实时双向通信的后台服务&#xff0c;第一时间就想到了WebSocket。虽然现在各种语言的WebSocket库满天飞&#xff0c;但考虑到性能、资源控制和与现有C代码库的无缝集成&#xff0c;最终还是决定用C来手搓一个。这听起来可能有点“硬核”…

作者头像 李华
网站建设 2026/7/9 15:54:07

Blender智能重拓扑革命:QRemeshify深度解析与实战指南

Blender智能重拓扑革命&#xff1a;QRemeshify深度解析与实战指南 【免费下载链接】QRemeshify A Blender extension for an easy-to-use remesher that outputs good-quality quad topology 项目地址: https://gitcode.com/gh_mirrors/qr/QRemeshify 在3D建模领域&…

作者头像 李华