bzoj 1012 [JSOI2008]最大数maxnumber

bzoj 1012 [JSOI2008]最大数maxnumber


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

Output
对于每一个查询操作,你应该按照顺序依次输出结果,每个结果占一行。
Sample Input
5 100
A 96Q 1
A 97
Q 1
Q 2
Sample Output
96
93
96


题外话

每次打题面总是很痛苦……有没有哪位大犇有种既快又美观的输入题面的方法,蒟蒻在线求教……


题解

这题我知道很多大犇肯定是用许多高大上的算法做的,想法很神奇!。但是呢,像我这种小蒟蒻,做完这道题有别的收获,因为我使用线段树做的。网上有很多线段树的代码,基本上都是略过,因为这种暴力的蒟蒻想法其它博主不屑去讲。但是我看到却如获至宝,因为这题的线段树想法就是完美(?)的线段树插入操作模版!那么下面我就详细讲讲这题的暴力思想,顺带也给自己复习一下线段树的插入操作(以这题为背景)。
线段树的插入操作其实并没有我们想的那么难,在本题中,一开始这颗线段树是空的,但是我们也可以认为是一颗所有节点权值为0的线段树,那么根据题意,我们处理Q这个操作时,无非就是线段是的询问操作,接下来的关键是A操作。首先我们由题目的值,每个测点中我们最多只需要建一颗节点个数为M的线段树即可,为什么呢,因为每个测点中只有M次操作,也就是说假设生成数据的人脑子出了问题偏爱插入操作,所有操作都是插入操作,那也只有M个节点被插入了这颗线段树中。其实线段树的插入操作我们可以不妨换种思维,假设要将权值为v的节点插入到数列的末尾,无非就是相当于将线段树相应的节点的权值从0改成v,那么就好理解了,所以我们可以将线段树的插入操作看成是一种变形的修改操作,或者根本就是一种修改操作。


奉上代码

#include<cstdio>
#include<algorithm> 
#define qmid(L,R) L+((R-L)>>1)
#define LL long long
using namespace std;
const int INFINITE=-4e18;
int n,tot;
LL st[4*200005],D;
inline int read_number(){
    LL ret=0;char ch=getchar();
    while (ch<'0'||ch>'9')ch=getchar();
    while (ch>='0'&&ch<='9')ret=ret*10+ch-48,ch=getchar();
    return ret;
}
inline char read_char(){
    char ret=getchar();
    while (ret=='\n'||ret==' ')ret=getchar();
    return ret;
}
inline void insert(int root,int L,int R,int k,int v){ //插入操作
    if (L==R){st[root]=v;return;} //如果到了叶子节点,那么就修改
    int mid=qmid(L,R);
    if (k<=mid)insert(root*2+1,L,mid,k,v);else insert(root*2+2,mid+1,R,k,v); //如果要插入的节点的位置小于mid那么就插入左儿子否则插入右儿子
    st[root]=max(st[root*2+1],st[root*2+2]);  //递归修改父亲节点
}
inline LL query(int root,int L,int R,int qL,int qR){  //询问操作
    if (L>qR||R<qL)return INFINITE;  //如果当前区间完全和要询问的区间搭不着边,那么就退无限小(也就是再怎样程序也不会取的的值)
    if (L>=qL&&R<=qR)return st[root];  //如果当前区间包含在询问区间内,那么就退这个区间的极值
    int mid=qmid(L,R);
    return max(query(root*2+1,L,mid,qL,qR),query(root*2+2,mid+1,R,qL,qR));  //分别询问左儿子右儿子
}
int main(){
    n=read_number(),D=read_number();
    LL lst=0;
    for (int i=1;i<=n;i++){
        char ch=read_char();int x=read_number(); 
//      putchar(ch),printf(" %d\n",x);
        if (ch=='A')insert(1,1,n,++tot,(x+lst)%D);
               else lst=query(1,1,n,tot-x+1,tot),printf("%lld\n",lst);
    }
    return 0;
}
/*
Sample Input
5 100
A 96
Q 1
A 97
Q 1
Q 2
*/

后记

这道题目我是将它当做线段树插入操作的经典题目来做的,当然网上还有另外的神奇算法,其中感觉比较简单的是单调栈,大家也可以去看看,毕竟题目不能AC了就了事了,还需要去看看他人的想法,这样才可以打通奇经八脉进一步提升自己。


weixin073智慧旅游平台开发微信小程序+ssm后端毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
python017基于Python贫困生资助管理系统带vue前后端分离毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值