[CSP-S模拟测试]:array(单调栈)
题目描述
在放完棋子之后,$dirty$又开始了新的游戏。
现在他拥有一个长为$n$的数组$A$,他定义第$i$个位置的分值为$i−k+1$,其中$k$需要满足:
对于任意满足$k\leqslant j\leqslant i$的$j$,有$A[k]\leqslant A[j]\leqslant A[i]$。当对于第$i$个数,有多个$k$满足条件时,取能获得较大分值的$k$。
现在,$dirty$想要知道$A$数组中分值最大的位置对应的分值为多少。
输入格式
第一行一个整数$n$,表示$A$数组的长度。
第二行$n$个整数,第$i$个数表示$A[i]$的值。
输出格式
输出一行一个整数,表示$A$数组中分值最大的位置对应的分值。
样例
样例输入:
8
8 6 1 7 9 2 3 8
样例输出:
3
数据范围与提示
注意由于$n$的范围较大,本题可能需要使用更快的读入方法。
对于$10\%$的数据,$n\leqslant 10^3$;
对于$40\%$的数据,$n\leqslant 3\times 10^5$;
对于另外$20\%$的数据为随机数据,且$n\leqslant 10^6$;
对于$100\%$的数据,$1\leqslant n\leqslant 10^7$;$1\leqslant A[i]\leqslant 10^9$。
题解
先来解释一下题意,对于区间$[k,i]$,我们只用保证中间的所有元素都大于等于$A[k]$,比小于等于$A[i]$即可,而不用关注其内部大小关系。
分值越大意味着$k$越小。
接下来说一下我考场上的思路,发现对于每一个$i$其最小的$k$位于其前面最后一个比它大的数之间最小的数,也就是如下图$\downarrow$

那么我们可以用单调栈维护第一个比它大的,然后用线段树查询区间最小值的位置即可,然后它就$\downarrow$

这个思路最傻的地方在于为何不用单调栈在维护一个最小值……
时间复杂度:$\Theta(n)$。
期望得分:$100$分。
实际得分:$100$分。
代码时刻
$60\%$算法:
#include<bits/stdc++.h>
#define int int_least32_t
#define L(x) x<<1
#define R(x) x<<1|1
using namespace std;
const int L=1<<20|1;
char buffer[L],*S,*T;
#define inline __attribute__((optimize("-O3")))
#define getchar() ((S==T&&(T=(S=buffer)+fread(buffer,1,L,stdin),S==T))?EOF:*S++)
int n;
int a[10000010];
int ans;
int trmin[40000010],pmin[40000010];
int sta[10000010],top;
inline int read(){
int ss(0);char bb(getchar());
while(bb<48||bb>57)bb=getchar();
while(bb>=48&&bb<=57)ss=(ss<<1)+(ss<<3)+(bb^48),bb=getchar();
return ss;
}
inline void pushup(int x)
{
if(trmin[L(x)]<=trmin[R(x)])
{
trmin[x]=trmin[L(x)];
pmin[x]=pmin[L(x)];
}
else
{
trmin[x]=trmin[R(x)];
pmin[x]=pmin[R(x)];
}
}
inline void build(int x,int l,int r)
{
if(l==r){trmin[x]=a[l];pmin[x]=l;return;}
int mid=(l+r)>>1;
build(L(x),l,mid);
build(R(x),mid+1,r);
pushup(x);
}
inline pair<int,int> askmin(int x,int l,int r,int L,int R)
{
if(r<L||R<l)return make_pair(-0x3f3f3f3f,0x3f3f3f3f);
if(L<=l&&r<=R)return make_pair(pmin[x],trmin[x]);
int mid=(l+r)>>1;
pair<int,int> lft=askmin(L(x),l,mid,L,R);
pair<int,int> rht=askmin(R(x),mid+1,r,L,R);
return lft.second<=rht.second?lft:rht;
}
int main()
{
n=read();
for(int i=1;i<=n;i++)a[i]=read();
a[n+1]=0x3f3f3f3f;
build(1,1,n+1);
for(int i=1;i<=n;i++)
{
while(top&&a[sta[top]]<=a[i])top--;
int flag=sta[top]+1;
sta[++top]=i;
if(i-flag<ans)continue;
pair<int,int> minn=askmin(1,1,n+1,flag,i);
ans=max(ans,i-minn.first+1);
}
printf("%d",ans);
return 0;
}
$100\%$算法:
#include<bits/stdc++.h>
using namespace std;
int n;
int a[10000001],sta[10000001],maxn[10000001];
int ans;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
{
while(sta[0]&&a[i]<a[sta[sta[0]]])
{
if(a[maxn[sta[0]-1]]<=a[maxn[sta[0]]])maxn[sta[0]-1]=maxn[sta[0]];
ans=max(ans,maxn[sta[0]]-sta[sta[0]]+1);
maxn[sta[0]--]=0;
}
sta[++sta[0]]=i;
maxn[sta[0]]=i;
}
while(sta[0])
{
if(a[maxn[sta[0]-1]]<=a[maxn[sta[0]]])maxn[sta[0]-1]=maxn[sta[0]];
ans=max(ans,maxn[sta[0]]-sta[sta[0]]+1);
maxn[sta[0]--]=0;
}
printf("%d",ans);
return 0;
}
rp++
[CSP-S模拟测试]:array(单调栈)的更多相关文章
- Educational Codeforces Round 23 D. Imbalanced Array 单调栈
D. Imbalanced Array time limit per test 2 seconds memory limit per test 256 megabytes input standard ...
- AtCoder Grand Contest 005【A栈模拟,B单调栈】
挖草,AtCoder实在是太吊了~ %%%,目前只A了两题: A题: 就是利用栈模拟一下就好了:S进栈,T的话有S就出栈,然后len减一下就好了: #include <bits/stdc++.h ...
- 「10.11」chess(DP,组合数学)·array(单调栈)·ants(莫队,并茶几)
菜鸡wwb因为想不出口胡题所以来写题解了 A. chess 昨天晚上考试,有点困 开考先花五分钟扫了一边题,好开始肝$T1$ 看了一眼$m$的范围很大,第一反应矩阵快速幂?? $n$很小,那么可以打$ ...
- 【单调栈】Vijos P1926 紫色的手链
题目链接: https://vijos.org/p/1926 题目大意: 给n个数(n<=100 000),求任意区间的最大值异或次大值的最大值. 题目思路: [模拟][单调栈] 我们维护一个严 ...
- [CSP-S模拟测试]:导弹袭击(数学+凸包+单调栈)
题目背景 $Guess$准备向敌军阵地发起进攻了!$Guess$的武器是自动制导导弹.然而在机房是不允许游戏的,所以班长$XZY$对游戏界面进行了降维打击,结果... 题目描述 众所周知,环境因素对导 ...
- [CSP-S模拟测试]:A(单调栈维护凸包+二分答案)
题目传送门(内部题150) 输入格式 第一行两个整数$N,Q$. 接下来的$N$行,每行两个整数$a_i,b_i$. 接下来的$Q$行,每行一个整数$x$. 输出格式 对于每个询问,输出一行一个整数表 ...
- [CSP-S模拟测试]:Cover(单调栈++单调队列+DP)
题目传送门(内部题126) 输入格式 第一行两个个整数$n,m$表示区间的长度与彩灯的数量. 接下来$m$行,每行三个整数$l_i,r_i,a_i$表示一条彩灯能够覆盖的区间以及它的美观程度. 输出格 ...
- [CSP-S模拟测试]:你相信引力吗(单调栈)
题目传送门(内部题124) 输入格式 第一行一个整数$n$代表环的长度. 第二行$n$个整数表示每个冰锥的高度. 输出格式 一行一个整数表示有多少对冰锥是危险的. 样例 样例输入1: 51 2 4 5 ...
- [CSP-S模拟测试]:陶陶摘苹果(线段树维护单调栈)
题目传送门(内部题116) 输入格式 第一行两个整数$n,m$,如题 第二行有$n$个整数表示$h_1-h_n(1\leqslant h_i\leqslant 10^9)$ 接下来有$m$行,每行两个 ...
随机推荐
- linux rz上传-sz下载
yum install lrzsz -y rz 上传文件 不能传目录 如果要传目录需要打包成文件再上传 需要往哪里传东西,先进入哪个目录 rz -y 上传覆盖 sz -y 文件名 ...
- java基础笔记(2)
java中成员变量是有默认初始值的,而局部变量是没有的: 构造方法名和类名相同,没有返回值,即结构如下:public 构造方法名(): 实例化类的本质就是调用了类的构造方法: 如果自定义了构造方法,就 ...
- 基于 Redux + Redux Persist 进行状态管理的 Flutter 应用示例
好久没在 SegmentFault 写东西,唉,也不知道 是忙还是懒,以后有时间 再慢慢写起来吧,最近开始学点新东西,有的写了,个人博客跟这里同步. 一直都在自己的 React Native 应用中使 ...
- hdu1465不easy系列之中的一个(错排)
版权声明:本文为博主原创文章,未经博主同意不得转载. vasttian https://blog.csdn.net/u012860063/article/details/37512659 转载请注明出 ...
- GeoAdapter实现WMS、WMTS、ArcGIS MapService的区域权限授权管理
背景: 在实际GIS应用中,我们经常会发布GIS地图服务,然后供WebGIS调用.在某些特殊情况下,需要对服务进行区域授权,特定的用户只能够浏览特定范围内的地图数据.通常情况下大家采用的实现方式是使用 ...
- 剑指offer-二叉搜索树的后序遍历序列-python
题目描述 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则输出Yes,否则输出No.假设输入的数组的任意两个数字都互不相同. 递归法: 先判断左子树是否存在 再判断右子树是否存 ...
- Math、Date内置对象方法整理
Math : 内置的对象(构造函数)静态属性或静态方法. 一. Math.PI : 圆周率 ...
- author认证模块
author认证模块 用auth模块 你就用全套 不是自己写一部分 用别人一部分 创建超级管理员,用于登录DJango admin的后台管理 命令:createsuperuser,输入顺序用户 ...
- 几个有关FPGA的概念
<数字设计——原理和实践>(John F.Wakerly)的书 FPGA同步时钟设计 简单说就是 一个系统中(或系统中的一部分)都采用同一个时钟触发.系统中的(D)触发器全部都连接到一个时 ...
- c/c++基础篇之数据类型转换
C/C++常见的数据类型转换 1. 常见的单类基本类型转换 (1)强制类型转换 如: int a=(int)(9.87) 结果a=9 char c=(char)(97) 结果为c=’a’ ...