BZOJ 1012: [JSOI2008]最大数maxnumber【线段树||单调栈】

news/2024/8/26 11:25:08

1012: [JSOI2008]最大数maxnumber

Time Limit: 3 Sec Memory Limit: 162 MB
Submit: 11990 Solved: 5202

【题目描述】

  现在请求你维护一个数列,要求提供以下两种操作:1、 查询操作。语法:Q L 功能:查询当前数列中末尾L
个数中的最大的数,并输出这个数的值。限制:L不超过当前数列的长度。2、 插入操作。语法:A n 功能:将n加
上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取
模,将所得答案插入到数列的末尾。限制:n是非负整数并且在长整范围内。注意:初始时数列是空的,没有一个
数。

【输入格式】

  第一行两个整数,M和D,其中M表示操作的个数(M <= 200,000),D如上文中所述,满足D在longint内。接下来
M行,查询操作或者插入操作。

【输出格式】

  对于每一个询问操作,输出一行。该行只有一个数,即序列中最后L个数的最大数。

【输入样例】

5 100
A 96
Q 1
A 97
Q 1
Q 2

【输出样例】

96
93
96
HINT

【解题报告】

这题读完其实就知道,其实它是要我们求一个会变化的区间最大值,但这个变化只是延长。
通过我们的经验,求区间最大值常用的就只有几个:
RMQ:但是RMQ只能求固定区间的极值,所以果断排除。
堆:这明显是不可以的。

那么我们就会想到线段树,但是也许你会说:“线段树也只能求固定区间的极值。”
其实你可以在建树的时候就先将位置预留下来,就可以了。
还有另一种线段树,不需要建树就可以的,也照样可以解。

其实仔细一想,完全可以用单调栈,反正他只是求最后几个,所以完全没问题。
我们建一个单调下降的栈,因为如果当前a[i]>a[j] (i>j)的话,a[j]根本就是无用的,永远也用不上,就像茅坑里的石头,又臭又硬,直接就可以扔掉不用。所以并不需要写麻烦的线段树,单调栈加二分查找轻松OK。

线段树代码:

#include<cstdio>
#include<algorithm>
using namespace std;
struct xcw{int L,R,c;}a[4*200005];
int n,tt,lst=0;
int read(){
    int ret=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-f;ch=getchar();}
    while(ch>='0'&&ch<='9') ret=ret*10+ch-48,ch=getchar();
    return ret*f;
}
void build(int p,int L,int R){//建树
    a[p]=(xcw){L,R,0};
    if(L==R) return;
    int mid=(R-L>>1)+L;
    build(p<<1,L,mid);build((p<<1)+1,mid+1,R);
}
void add(int p,int x,int y){//在x位置上添加y
    int L=a[p].L,R=a[p].R;
    if(x==L&&x==R){a[p].c=y;return;}
    int mid=(R-L>>1)+L;
    if(x<=mid) add(p<<1,x,y);else add((p<<1)+1,x,y);
    a[p].c=max(a[p<<1].c,a[(p<<1)+1].c);
}
int cnt(int p,int L,int R){//取出L到R之间的最大值
    if(a[p].L==L&&a[p].R==R) return a[p].c;
    int mid=(a[p].R-a[p].L>>1)+a[p].L;
    if(R<=mid) return cnt(p<<1,L,R);else
    if(L>mid) return cnt((p<<1)+1,L,R);else return max(cnt(p<<1,L,mid),cnt((p<<1)+1,mid+1,R));
}
int main(){
    n=read(),tt=read();
    build(1,1,n);
    int c=0;
    for(int i=1;i<=n;i++){
        char ch=getchar();
        if(ch=='Q'){
            int L=read();
            if(!lst) printf("0\n");else//如果没有元素时,肯定是0
            if(L>lst) printf("%d\n",c=cnt(1,1,lst));//超过现在的长度时,就是从1开始
            else printf("%d\n",c=cnt(1,lst-L+1,lst));
        }else{
            int y=read();
            add(1,++lst,(y+c)%tt);
        }
    }
    return 0;
}

单调栈代码:

#include<cstdio>
using namespace std;
int n,tt,tl,que[200005],id[200005],lst,c;
int read(){
    int ret=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-f;ch=getchar();}
    while(ch>='0'&&ch<='9') ret=ret*10+ch-48,ch=getchar();
    return ret*f;
}
int fnd(int x){//查找x的位置
    int L=1,R=tl;
    while(L<=R){
        int mid=(R-L>>1)+L;
        if(id[mid-1]<x&&id[mid]>=x) return que[mid];//如果x在这之间,que[mid]是最大的,因为栈是单调下降的,而mid-1不满足条件。
        if(id[mid]>=x) R=mid-1;else L=mid+1;
    }
}
int main(){
    n=read();tt=read();
    for(int i=1;i<=n;i++){
        char ch=getchar();
        if(ch=='Q'){
            int L=read();
            if(!lst) printf("0\n");else //栈为空
            if(L>lst) printf("%d\n",c=que[1]); //超过当前长度时,就是1号元素
            else printf("%d\n",c=fnd(lst-L+1));
        }else{
            int y=read(),now=(y+c)%tt;
            while(que[tl]<now&&tl) tl--; //去除不必要的元素,保证单调下降
            que[++tl]=now;id[tl]=++lst;
        }
    }
    return 0;
}

转载于:https://www.cnblogs.com/XSamsara/p/9059489.html


http://www.niftyadmin.cn/n/818922.html

相关文章

学习Java spring框架工作原理-动力节点

Java spring框架学习&#xff0c;框架的工作原理&#xff0c;Spring是一种多层的J2EE应用程序框架&#xff0c;其核心就是提供一种新的机制管理业务对象及其依赖关系。它是一种容器框架&#xff0c;用于创建bean&#xff0c;维护bean之间的关系&#xff0c;它可以管理Web层、持…

亚马逊被曝将裁员 1 万人,史上规模最大

推荐阅读&#xff1a;《马斯克又裁 4400 合同工。》《就聊挣钱社群招募公告。》1这次是亚马逊这段时间写裁员都写麻了。现在不是哪个大厂裁员是新闻&#xff0c;而是哪个大厂裁员最狠才算是新闻&#xff0c;比如推特裁员50%&#xff0c;Meta 再来个1万。这回轮到了电商巨头&…

SurfaceView实现UI系统

最初的想法是通过SurfaceView来实现UI&#xff0c;后来实验了一下&#xff0c;在目标板子上帧率太低&#xff0c;动画效果出不来。后来转向Angle。再后来Angle也遇到一些问题&#xff0c;又转回头研究SurfaceView&#xff0c;发现之前的绘图策略存在问题&#xff0c;用SurfaceV…

DevOps之一 Gitlab的安装与配置

gitlab的安装 参考治疗&#xff1a;https://www.gitlab.com.cn/installation/#centos-7 http://www.21yunwei.com/archives/4351 1.安装并配置必要的依赖关系 如果你想使用 Postfix 发送邮件&#xff0c;请在安装过程中根据提示选择 Internet Site。 你也可以用 Sendmail 或者 …

五个值得关注的java深度学习框架-动力节点

DeepMind宣布采用谷歌开源的深度学习框架TensorFlow&#xff0c;不再采用Torch框架。Torch诞生时间较久&#xff0c;直到去年Facebook开源了大量Torch的深度学习模块才开始流行起来。 DeepMind是谷歌并购的一家AI公司&#xff0c;今年因AlphaGo以4:1的成绩战胜了韩国围棋大师李…

Spring--java.sql.SQLException: Access denied for user 'XXXXX'@'localhost' (using password: YES)

目录 问题一&#xff1a; 问题二&#xff1a; 解决方案&#xff1a; 在IntelliJ IDEA上整合Mybatis和Spring的&#xff0c;运行测试用例出现了如上错误。红色的马赛克部分是我的名字。 问题一&#xff1a; 数据库里面没有以我名字为用户名的用户。而只有IntelliJIDEA是用我…

说马斯克不懂技术瞎比比,工程师被在线开除!

今天推文之前&#xff0c;给大家介绍一个朋友。平时我周边很少能遇到持续日更的公众号作者&#xff0c;前两天在跟朋友吃饭的时候有幸结识了一位大佬&#xff0c;他叫少峰。一个纯分享型大佬&#xff0c;互联网创业史15年&#xff0c;公司员工二百多人&#xff0c;公众号500多篇…

libevent http client

我自己在实现一个http client&#xff0c;使用libevent&#xff0c;遇到一些问题&#xff0c;连接可以建立&#xff0c;但发送http请求后毫无反应。实验了windows和linux两个版本&#xff0c;都是如此。可能还是我使用上的问题。 请给我的决赛文章《Qt Quick 图像处理实例之美图…