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

皇家守卫【算法赛】、百亿富翁、最大区间、附近最小

皇家守卫【算法赛】

问题描述

在蓝桥王国的边疆有 NN​ 座高塔,每座高塔上均有一个士兵,他们被称之为皇家守卫。

每座高塔均有一个高度,第 ii 座高塔的高度为 hihi​。对于第 ii 座塔,若其右边存在某座塔 jj,满足:max⁡(hi,hi+1,hi+2,⋯,hj−1)<hjmax(hi​,hi+1​,hi+2​,⋯,hj−1​)<hj​则称第 jj 座塔为第 ii 座塔 "暸望塔"。

现在王国传来 QQ 个任务,每个任务会给定两个编号 x,yx,y,需要你求解第 xx 座高塔和 第 yy 座高塔的公共 "暸望塔" 数量。

x,yx,y 的公共 "暸望塔" 定义为两者同时拥有的 "暸望塔"。

输入格式

第一行输入两个整数 N,Q(1≤N,Q≤105)N,Q(1≤N,Q≤105) 表示高塔个数和任务数。

第二行输入 NN 个整数 h1,h2,h3,⋯,hn(1≤hi≤109)h1​,h2​,h3​,⋯,hn​(1≤hi​≤109) 表示高塔的高度。

接下来 QQ 行,每行输入两个整数 x,y(1≤x≤y≤N)x,y(1≤x≤y≤N) 表示一次任务询问。

输出格式

输出 QQ 行,每行一个整数表示答案

输入样例

5 3 1 3 4 5 7 1 3 2 4 3 5

输出样例

2 1 0

说明

对于第一个询问,第 11 座高塔和第 33 座高塔的公共暸望塔有 4,54,5 号塔。

暴力(超时)

import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.HashSet; import java.util.Set; public class Main { static int N = 100010; static int a[]=new int[N]; public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String g[] = br.readLine().split(" "); int n=Integer.parseInt(g[0]),q=Integer.parseInt(g[1]); g = br.readLine().split(" "); for (int i = 1; i <= n; i++) { a[i]=Integer.parseInt(g[i-1]); } Set<Integer> set1=new HashSet<>(); Set<Integer> set2=new HashSet<>(); for (int i = 0; i < q; i++) { g = br.readLine().split(" "); int u=Integer.parseInt(g[0]),v=Integer.parseInt(g[1]); valid(u,n,set1);valid(v,n,set2); long res=0; for(int k1:set1){ for(int k2:set2){ if(k1==k2)res++; } } System.out.println(res); set1=new HashSet<>();set2=new HashSet<>(); } } static void valid(int x,int n,Set<Integer> set){ int pastMax=a[x]; for (int i = x+1; i <= n; i++) { if(a[i]>pastMax){ set.add(i); pastMax=a[i]; } } } }

单调栈+倍增优化

import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.Stack; public class Main { static int N = 100010; static int a[]=new int[N]; static int next[]=new int[N];//表示右边第一个比我大的数的下标 static int len[]=new int[N];//表示从i开始 暸望塔的数量 public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String g[] = br.readLine().split(" "); int n=Integer.parseInt(g[0]),q=Integer.parseInt(g[1]); g = br.readLine().split(" "); for (int i = 1; i <= n; i++) { a[i]=Integer.parseInt(g[i-1]); } a[n+1]=Integer.MAX_VALUE;//哨兵 确保能找到右边比我大的数 Stack<Integer> stack=new Stack<>();//维护一个单调递减的栈 for (int i = n; i >=1 ; i--) { int num=a[i]; while(!stack.isEmpty() && a[stack.peek()]<=num){//必须加等号 stack.pop(); } if(!stack.isEmpty())next[i]=stack.peek(); else next[i]=n+1; stack.add(i); } next[n+1] = n+1; // 需要这句 for (int i = n; i >= 1; i--) { if(next[i]<=n){ len[i]=len[next[i]]+1; }else{ len[i]=0; } } int k=18; int go[][]=new int[n+2][k]; for (int i = 1; i <= n+1; i++) { go[i][0]=next[i]; } for (int j = 1; j < k; j++) {//倍增表要求第二维在外层 for (int i = 1; i <= n+1; i++) { go[i][j]=go[go[i][j-1]][j-1]; } } for (int i = 0; i < q; i++) { g = br.readLine().split(" "); int u=Integer.parseInt(g[0]),v=Integer.parseInt(g[1]); int uu=u; int step=0; for (int j = k-1; j >=0; j--) { if(go[u][j]<=v){ step+=1<<j; u=go[u][j]; } } System.out.println(len[uu]-step); } } }

百亿富翁

题目描述

这天小明买彩票中了百亿奖金,兴奋的他决定买下蓝桥公司旁的一排连续的楼房。

已知这排楼房一共有 NN 栋,编号分别为 1∼N1∼N,第 ii 栋的高度为 hihi​。

好奇的小明想知道对于每栋楼,左边第一个比它高的楼房是哪个,右边第一个比它高的楼房是哪个(若不存在则输出 −1−1)。但由于楼房数量太多,小明无法用肉眼直接得到答案,于是他花了 11 个亿来请你帮他解决问题,你不会拒绝的对吧?

输入描述

第 11 行输入一个整数 NN,表示楼房的数量。

第 22 行输入 NN 个整数(相邻整数用空格隔开),分别为 h1,h2,...,hNh1​,h2​,...,hN​,表示楼房的高度。

1≤N≤7×1051≤N≤7×105,1≤hi≤1091≤hi​≤109。

输出描述

输出共两行。

第一行输出 NN 个整数,表示每栋楼左边第一栋比自己高的楼的编号。

第二行输出 NN 个整数,表示每栋楼右边第一栋比自己高的楼的编号。

输入输出样例

示例 1

输入

5 3 1 2 5 4

输出

-1 1 1 -1 4 4 3 4 -1 -1
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.Stack; public class Main { static int N = 7*100010; static int a[]=new int[N]; static int left[]=new int[N];//表示左边边第一个比我大的数的下标 static int right[]=new int[N];//表示左边边第一个比我大的数的下标 public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // String g[] = br.readLine().split(" "); int n=Integer.parseInt(br.readLine()); String g[] = br.readLine().split(" "); for (int i = 0; i < n; i++) { a[i]=Integer.parseInt(g[i]); } //维护一个单调递减的栈 Stack<Integer> stack=new Stack<>(); for (int i = 0; i < n; i++) { while(!stack.isEmpty() && a[stack.peek()]<=a[i])stack.pop(); if(!stack.isEmpty())left[i]=stack.peek(); else left[i]=-1; stack.add(i); } Stack<Integer> stack1=new Stack<>(); for (int i = n-1; i>=0; i--) { while(!stack1.isEmpty() && a[stack1.peek()]<=a[i])stack1.pop(); if(!stack1.isEmpty())right[i]=stack1.peek(); else right[i]=-1; stack1.add(i); } for (int i = 0; i < n; i++) { if(left[i]!=-1)System.out.print(left[i]+1+" "); else System.out.print("-1 "); } System.out.println(); for (int i = 0; i < n; i++) { if(right[i]!=-1)System.out.print(right[i]+1+" "); else System.out.print("-1 "); } } }

最大区间

问题描述

给定一个长度为 nn 的序列 AiAi​,求 L,RL,R 使 (R−L+1)⋅min⁡(AL,AL+1,…,AR)(R−L+1)⋅min(AL​,AL+1​,…,AR​) 尽可能大,其中 min⁡min 表示最小值。

你只需要输出最大的值即可,不需要输出具体的 L,RL,R。

输入格式

输入的第一行包含一个整数 nn。

第二行包含 nn 个整数,分别表示 A1,A2,…,AnA1​,A2​,…,An​,相邻两个整数之间使用一个空格分隔。

输出格式

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

样例输入

5 1 1 3 3 1

样例输出

6

评测用例规模与约定

对于 40%40% 的评测用例,1≤n≤50001≤n≤5000,1≤Ai≤50001≤Ai​≤5000;

对于所有评测用例,1≤n≤3×1051≤n≤3×105,1≤Ai≤1091≤Ai​≤109。

单调队列超时

import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class Main { static int N = 3*100010; static int a[]=new int[N]; static int q[]=new int[N]; public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // String g[] = br.readLine().split(" "); int n=Integer.parseInt(br.readLine()); String g[] = br.readLine().split(" "); for (int i = 0; i < n; i++) { a[i]=Integer.parseInt(g[i]); } int head=0,tail=0; //维护一个单调递增队列队列 long res=Long.MIN_VALUE; for (int k = 1; k <= n; k++) {//滑动窗口的大小 head=0;tail=0; for (int i = 0; i < n; i++) { if(i-q[head]>=k)head++; while(tail-head>0 && a[q[tail-1]]>=a[i])tail--; q[tail++]=i; if(i>=k-1)res=Math.max(res,(long)k*a[q[head]]);// 此句条件一定不要忘 } } System.out.println(res); } }

单调栈

import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.lang.Thread.State; import java.util.Stack; public class Main { static int N = 3*100010; static int a[]=new int[N]; static int right[]=new int[N]; static int left[]=new int[N]; public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // String g[] = br.readLine().split(" "); int n=Integer.parseInt(br.readLine()); String g[] = br.readLine().split(" "); for (int i = 0; i < n; i++) { a[i]=Integer.parseInt(g[i]); } //维护一个单调递增栈 //对于每一个数 向左右扩展找到第一个小于我的数 Stack<Integer> stack=new Stack<>(); for (int i = 0; i < n; i++) { while(!stack.isEmpty() && a[stack.peek()]>=a[i])stack.pop(); if(!stack.isEmpty())left[i]=stack.peek(); else left[i]=-1; stack.add(i); } Stack<Integer> stack1=new Stack<>(); for (int i = n-1; i >= 0; i--) { while(!stack1.isEmpty() && a[stack1.peek()]>=a[i])stack1.pop(); if(!stack1.isEmpty())right[i]=stack1.peek(); else right[i]=n; stack1.add(i); } long res=Long.MIN_VALUE; for (int i = 0; i < n; i++) { //System.out.println(left[i]+" "+right[i]); res=Math.max(res,(long)(right[i]-left[i]-1)*a[i]); } System.out.println(res); } }

附近最小

问题描述

小蓝有一个序列 a[1],a[2],...,a[n]a[1],a[2],...,a[n]。

给定一个正整数 kk,请问对于每一个 11 到 nn 之间的序号 ii,a[i−k],a[i−k+1],...,a[i+k]a[i−k],a[i−k+1],...,a[i+k] 这 2k+12k+1 个数中的最小值是多少?

当某个下标超过 11 到 nn 的范围时,数不存在,求最小值时只取存在的那些值。

输入格式

输入的第一行包含一整数 nn。

第二行包含 nn 个整数,分别表示 a[1],a[2],...,a[n]a[1],a[2],...,a[n]。

第三行包含一个整数 kk 。

输出格式

输出一行,包含 nn 个整数,分别表示对于每个序号求得的最小值。

样例输入

样例输出

2 2 2 3 3

评测用例规模与约定

对于 30% 的评测用例,1<=n<=1000,1<=a[i]<=10001<=n<=1000,1<=a[i]<=1000。

对于 50% 的评测用例,1<=n<=10000,1<=a[i]<=100001<=n<=10000,1<=a[i]<=10000。

对于所有评测用例,1<=n<=1000000,1<=a[i]<=10000001<=n<=1000000,1<=a[i]<=1000000。

import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class Main { static int N = 2*1000010; static int a[]=new int[N],ind; static int q[]=new int[N]; static int res[]=new int[N]; public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // String g[] = br.readLine().split(" "); int n=Integer.parseInt(br.readLine()); String g[] = br.readLine().split(" "); int k=Integer.parseInt(br.readLine()); int kk=k; for (int i = 0; i < k; i++) { a[ind++]=Integer.MAX_VALUE; } for (int i = 0; i < n; i++) { a[ind++]=Integer.parseInt(g[i]); } for (int i = 0; i < k; i++) { a[ind++]=Integer.MAX_VALUE; } k=2*k+1; //维护一个单调递增的队列 int tail=0,head=0; for (int i = 0; i < ind; i++) { if(tail-head>0 && i-q[head]>=k)head++; while(tail-head>0 && a[q[tail-1]]>=a[i])tail--; q[tail++]=i; if(i>=k-1)res[i]=a[q[head]]; } for (int i = k-1 ; i < k+n-1; i++) { System.out.print(res[i]+" "); } } }
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class Main { static int N = 2*1000010; static int a[]=new int[N],ind; static int q[]=new int[N]; static int res[]=new int[N]; public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // String g[] = br.readLine().split(" "); int n=Integer.parseInt(br.readLine()); String g[] = br.readLine().split(" "); int k=Integer.parseInt(br.readLine()); for (int i = 0; i < n; i++) { a[i]=Integer.parseInt(g[i]); } //维护一个单调递增的队列 int tail=0,head=0,r=-1;//要添加一次左边界的最大值 for (int i = 0; i < n; i++) { int left=Math.max(0, i-k); int right=Math.min(n-1, i+k); while(tail-head>0 && q[head]<left)head++; while (r < right) { r++; while (tail - head > 0 && a[q[tail - 1]] >= a[r]) tail--; q[tail++] = r; } res[ind++]=a[q[head]]; } for (int i = 0; i < ind; i++) { System.out.print(res[i]+" "); } } }
http://www.jsqmd.com/news/927546/

相关文章:

  • 深入聊聊FPGA网络通信:为什么一个纯Verilog实现的、不带Ping功能的UDP协议栈反而更“香”?
  • Castkit:基于Rust的CLI演示视频自动化生成工具
  • 厨房里的化学生态用鸿蒙PC的Electron框架实现
  • 2026年湘潭市黄金回收靠谱门店推荐 黄金+K金+白银+铂金回收门店TOP5排行榜+联系方式 - 盛世金银回收
  • 用Python复现数学建模国赛C题:手把手教你用遗传算法优化电商物流网络(附完整代码)
  • 【鸿蒙原生应用开发--ArkUI--015】File-manager 文件管理器应用开发教程
  • dify一些bug解决
  • yolov26改进 | Conv/卷积篇 | 轻量化多尺度异构卷积(MSHC)优化YOLOv26精度(附独家网络结构图)
  • 别再傻傻分不清!用Python实战演示标准差、标准误和置信区间的区别(附代码)
  • HPC构建系统:GPU加速与并行编程优化指南
  • 别再踩坑了!STM32H7的MPU内存属性配置详解(附DMA与Cache协作最佳实践)
  • 小爱音箱语音播放不下载音乐?一招解锁智能下载功能终极指南
  • 【鸿蒙原生应用开发--ArkUI--016】Guess-number 猜数字游戏开发教程
  • AI内容如何通过E-E-A-T框架提升SEO效果:策略与实战指南
  • 2026年襄阳市黄金回收靠谱门店推荐 黄金+K金+白银+铂金回收门店TOP5排行榜+联系方式 - 盛世金银回收
  • 用SpikingJelly的泊松编码器给Lena图像‘打码’:一个脉冲神经网络入门实验
  • 用YOLOv8和RealSense D415给篮球拍个3D‘X光’:手把手教你提取目标点云
  • ESP32-C3开发踩坑记:我把Panic Handler从‘无限重启’改成‘原地挂起’,调试效率翻倍了
  • R语言实战:用`caret`和`tidymodels`一键计算MSE,搞定模型交叉验证
  • WebUncertainty框架:用不确定性建模提升AI智能体在动态网页任务中的鲁棒性
  • Qt桌面应用数据层实战:基于QxOrm封装一个可复用的Model类
  • 从AirPods Pro到索尼XM5:拆解主流ANC耳机背后的‘混合动力’(Hybrid)技术到底强在哪?
  • 别再只会ping了!用traceroute/tracert命令5分钟定位网络卡顿元凶(附Linux/Windows实战对比)
  • 博弈论与AI/NLP融合:从策略交互到智能决策实战
  • PyTorch数据流水线实战:从Dataset构建到DataLoader优化的完整指南
  • 2026年孝感市黄金回收靠谱门店推荐 黄金+K金+白银+铂金回收门店TOP5排行榜+联系方式 - 盛世金银回收
  • 西班牙语数据科学学习路径:从Python基础到BERT模型部署
  • AI为何讲不好笑话?从大语言模型原理到幽默生成的局限性分析
  • 2026年忻州市黄金回收靠谱门店推荐 黄金+K金+白银+铂金回收门店TOP5排行榜+联系方式 - 盛世金银回收
  • 告别MATLAB依赖!手把手教你用App Designer打包独立桌面软件(含Runtime组件)