BZOJ 1012: [JSOI2008]最大数maxnumber kevin_xcw
来源:互联网 发布:js设置input宽度 编辑:程序博客网 时间:2024/06/07 01:19
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;}
- BZOJ 1012: [JSOI2008]最大数maxnumber kevin_xcw
- BZOJ 1012: [JSOI2008]最大数maxnumber
- BZOJ 1012 [JSOI2008]最大数maxnumber
- BZOJ 1012: [JSOI2008]最大数maxnumber
- [BZOJ 1012][JSOI2008]最大数maxnumber
- BZOJ 1012: [JSOI2008]最大数maxnumber
- bzoj 1012: [JSOI2008]最大数maxnumber 二分
- bzoj 1012 [JSOI2008]最大数maxnumber
- [BZOJ 1012] [JSOI2008] 最大数maxnumber
- 【BZOJ 1012】[JSOI2008]最大数maxnumber
- BZOJ 1012:[JSOI2008]最大数 maxnumber
- bzoj 1012 [JSOI2008]最大数maxnumber
- 【BZOJ 1012】 [JSOI2008]最大数maxnumber
- bzoj 1012 [JSOI2008]最大数maxnumber
- BZOJ 1012 [JSOI2008]最大数maxnumber
- BZOJ 1012 [JSOI2008]最大数maxnumber
- BZOJ 1012: [JSOI2008]最大数maxnumber
- BZOJ 1012: [JSOI2008]最大数maxnumber
- Python学习数据结构、输入输出、文件对象
- python的文件读写笔记
- spark参数调优
- Java中String与byte[]的转换
- NAT穿越技术(二)
- BZOJ 1012: [JSOI2008]最大数maxnumber kevin_xcw
- 一看就懂的自定义顶部粘性下拉控件TouchPullView全面剖析
- Kaggle大神带你上榜单Top2%:点击预测大赛纪实(上)
- C# 中转义符及特殊符号的使用
- Java设计模式,概念以及实际例子
- HTTP 协议入门
- hive多个字节分割符
- cocos2dx : 导演类中的常见用法.
- 对于指针应用const的理解