[JSOI2008]最大数maxnumber
2015-07-27 17:35
676 查看
1012: [JSOI2008]最大数maxnumber
Time Limit: 3 Sec Memory Limit: 162 MBSubmit: 5667 Solved: 2461
[Submit][Status][Discuss]
Description
现在请求你维护一个数列,要求提供以下两种操作: 1、 查询操作。语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值。限制:L不超过当前数列的长度。 2、 插入操作。语法:A n 功能:将n加上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取模,将所得答案插入到数列的末尾。限制:n是非负整数并且在长整范围内。注意:初始时数列是空的,没有一个数。
Input
第一行两个整数,M和D,其中M表示操作的个数(M <= 200,000),D如上文中所述,满足(0
Output
对于每一个查询操作,你应该按照顺序依次输出结果,每个结果占一行。
Sample Input
5 100A 96
Q 1
A 97
Q 1
Q 2
Sample Output
9693
96
HINT
Source
1.单调队列,比较好理解,就是如果要新加入的数比前面若干个数大,就把这若干个数覆盖掉,通俗点说,又靠后值又大的数比较diao,因为撑死20w个数,所以开两个20w的数组就够了。 我们平时写单调队列时,貌似比较多的是用两个指针head,tail来维护队列Q[]数组,但这题貌似行不通,因为每次询问的L不固定,不能舍弃数列的任意一部分,所以用了“覆盖”的方法。注意:在输入字符A或Q时,如果像我下面那样定义ch[5],用 cin>>ch 是错的,要用scanf("%s",ch); 否则会RE,我也不知道为啥
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int Q[200005]; int a[200005]; char ch[5]; int L,N,T,D,M,tot; inline void workA(); inline void workQ(); int main(){ cin>>M>>D; for(int i=1;i<=M;i++){ scanf("%s",ch); //cin>>ch;//RE的 if(ch[0]=='A') workA(); else workQ(); } return 0; } inline void workA(){ scanf("%d",&N); a[++tot]=(T+N)%D; for(int i=tot;i;i--){ if(Q[i]<a[tot]) Q[i]=a[tot]; else break; } } inline void workQ(){ scanf("%d",&L); printf("%d\n",T=Q[tot-L+1]); }
2.用线段树,相比之下太长了,还容易错,就不分析了,网上随便整的一个代码
#include<iostream> #include<cstdio> #define inf 0x7fffffff using namespace std; int m,mod,last,cnt; struct data{int l,r,mx;}t[800005]; void build(int k,int l,int r) { t[k].l=l;t[k].r=r;t[k].mx=-inf; if(l==r)return; int mid=(l+r)>>1; build(k<<1,l,mid); build(k<<1|1,mid+1,r); } int ask(int k,int x,int y) { int l=t[k].l,r=t[k].r; if(l==x&&r==y)return t[k].mx; int mid=(l+r)>>1; if(y<=mid)return ask(k<<1,x,y); else if(x>mid)return ask(k<<1|1,x,y); else return max(ask(k<<1,x,mid),ask(k<<1|1,mid+1,y)); } void insert(int k,int x,int y) { int l=t[k].l,r=t[k].r; if(l==r){t[k].mx=y;return;} int mid=(l+r)>>1; if(x<=mid)insert(k<<1,x,y); else insert(k<<1|1,x,y); t[k].mx=max(t[k<<1].mx,t[k<<1|1].mx); } int main() { scanf("%d%d",&m,&mod); build(1,1,m); for(int i=1;i<=m;i++) { char ch[5];scanf("%s",ch); int x; if(ch[0]=='A') { cnt++; scanf("%d",&x);x=(x+last)%mod; insert(1,cnt,x); } else { scanf("%d",&x); last=ask(1,cnt-x+1,cnt); printf("%d\n",last); } } return 0; }
相关文章推荐
- JavaScript(三) 正则表达式 以及实现的功能
- JavaScript数组对象实现增加一个返回随机元素的方法
- JS多语种方式
- javascript
- 批量删除的js代码
- js动态创建多个input框带删除按钮
- 使用HTML+CSS+JS制作简单的网页菜单界面
- js传值到后台中文乱码解决方法
- Javascript验证Visa和MasterCard信用卡号的方法
- scrollLeft的必要条件
- JavaScript实现自动对页面上敏感词进行屏蔽的方法
- JS下高效拼装字符串的几种方法比较与测试代码
- js代码在浏览器地址栏执行
- js字符串对象操作
- js 每秒刷新系统时间,可停止
- BJS实现Amazon RDS 多可用区域部署
- js自动刷新页面代码
- JSON数据的生成
- base64的js实现
- select元素javascript常用操作 转