1012: [JSOI2008]最大数maxnumber

Time Limit: 3 Sec  Memory Limit: 162 MB
Submit: 5425  Solved: 2397
[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 100
A 96
Q 1
A 97
Q 1
Q 2

Sample Output

96
93
96

HINT

Source

题解:先写个线段树拿分再说。不过我的处理方式很奇怪?不过幸好常数小。。。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<queue>
 6 #include<cstring>
 7 #define PAU putchar(' ')
 8 #define ENT putchar('\n')
 9 #define CH for(int d=0;d<2;d++) if(ch[d])
10 #define lson x->ch[0],L,M
11 #define rson x->ch[1],M+1,R
12 using namespace std;
13 const int maxn=200000+10,maxnode=400000+10,inf=-1u>>1;
14 int mod,last,ql,qr,pos,cv,_mx,n,len=0;
15 struct node{
16     node*ch[2];int mx;node(){mx=-inf;}
17     void update(){mx=-inf;CH{if(ch[d]->mx>mx)mx=ch[d]->mx;}return;}
18 }seg[maxnode],*nodecnt=seg,*root;
19 void build(node*&x=root,int L=1,int R=n){
20     x=nodecnt++;if(L==R)return;int M=L+R>>1;build(lson);build(rson);return;
21 }
22 void update(node*&x,int L,int R){
23     if(L==R){x->mx=cv;return;}int M=L+R>>1;
24     if(pos<=M)update(lson);else update(rson);x->update();
25 }
26 void query(node*x,int L,int R){
27     if(ql<=L&&R<=qr){_mx=max(_mx,x->mx);return;}int M=L+R>>1;
28     if(ql<=M)query(lson);if(qr>M)query(rson);return;
29 }
30 inline int read(){
31     int x=0,sig=1;char ch=getchar();
32     while(!isdigit(ch)){if(ch=='-') sig=-1;ch=getchar();}
33     while(isdigit(ch)) x=10*x+ch-'0',ch=getchar();
34     return x*sig;
35 }
36 inline void write(int x){
37     if(x==0){putchar('0');return;}if(x<0) putchar('-'),x=-x;
38     int len=0,buf[15];while(x) buf[len++]=x%10,x/=10;
39     for(int i=len-1;i>=0;i--) putchar(buf[i]+'0');return;
40 }
41 inline char readc(){
42     char ch=getchar();for(;!isalpha(ch);ch=getchar());return ch;
43 }
44 void init(){
45     n=read();mod=read();build();
46     for(int i=1;i<=n;i++){
47         if(readc()=='A')cv=(last+read())%mod,len++,pos=len,update(root,1,n);
48         else{
49             _mx=-inf;ql=len-read()+1;qr=len;query(root,1,n);write(_mx);ENT;last=_mx;
50         }
51     }
52     return;
53 }
54 void work(){
55     return;
56 }
57 void print(){
58     return;
59 }
60 int main(){
61     init();work();print();return 0;
62 }

当然这道题还有一个神奇的做法:观察到如果一个数出现在某个数后边,并且这个数大于之前的数,那么之前的数无论如何也不会成为最大的数的。

所以我们可以维护一个单调的东西。然后就没有然后了。

还有,以后别写二分了!!!!!!!

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<queue>
 6 #include<cstring>
 7 #define PAU putchar(' ')
 8 #define ENT putchar('\n')
 9 using namespace std;
10 const int maxn=200000+10,inf=-1u>>1;
11 int s[maxn],top=0,n,mod,v[maxn],len=0,last;
12 inline int read(){
13     int x=0,sig=1;char ch=getchar();
14     while(!isdigit(ch)){if(ch=='-') sig=-1;ch=getchar();}
15     while(isdigit(ch)) x=10*x+ch-'0',ch=getchar();
16     return x*=sig;
17 }
18 inline void write(int x){
19     if(x==0){putchar('0');return;}if(x<0) putchar('-'),x=-x;
20     int len=0,buf[15];while(x) buf[len++]=x%10,x/=10;
21     for(int i=len-1;i>=0;i--) putchar(buf[i]+'0');return;
22 }
23 inline char readc(){
24     char ch=getchar();for(;!isalpha(ch);ch=getchar());return ch;
25 }
26 void init(){
27     n=read();mod=read();
28     for(int i=1;i<=n;i++){
29         if(readc()=='A'){
30             int cv=(read()+last)%mod;
31             v[++len]=cv;
32             while(top&&v[s[top]]<=cv)top--;
33             s[++top]=len;
34         } else {
35             int pos=lower_bound(s+1,s+top+1,len-read()+1)-s;
36             write(last=v[s[pos]]);ENT;
37         }
38     }
39     return;
40 }
41 void work(){
42     return;
43 }
44 void print(){
45     return;
46 }
47 int main(){
48     init();work();print();return 0;
49 }

GYH神犇还提出了离线RMQ的思想。可以发现,每一次插入数即为新建一个集合,而删除一个数即将两集合合并,每次询问则为查询一个数所在的集合的代表元素。这正好是并查集所支持的各种操作。而并查集的每次操作的均摊复杂度接近O(1),所以RMQ的离线问题也可以在O(N+Q)的时间内解决,空间复杂度也是O(N+Q)。

但是。。。这个跟普通的二分跑得差不多,不过代码复杂度少了很多。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<queue>
 6 #include<cstring>
 7 #define PAU putchar(' ')
 8 #define ENT putchar('\n')
 9 using namespace std;
10 const int maxn=200000+10;
11 int stack[maxn],top=0,fa[maxn],A[maxn];
12 int find(int x){if(fa[x]==x)return x;return fa[x]=find(fa[x]);}
13 inline int read(){
14     int x=0,sig=1;char ch=getchar();
15     while(!isdigit(ch)){if(ch=='-') sig=-1;ch=getchar();}
16     while(isdigit(ch)) x=10*x+ch-'0',ch=getchar();
17     return x*=sig;
18 }
19 inline void write(int x){
20     if(x==0){putchar('0');return;}if(x<0) putchar('-'),x=-x;
21     int len=0,buf[15];while(x) buf[len++]=x%10,x/=10;
22     for(int i=len-1;i>=0;i--) putchar(buf[i]+'0');return;
23 }
24 inline char readc(){
25     char ch=getchar();while(!isalpha(ch))ch=getchar();return ch;
26 }
27 void init(){
28     int last=0,m,mod,x,len=0;
29     m=read();mod=read();
30     for(int i=1;i<=m;i++) fa[i]=i;
31     while(m--){
32         if(readc()=='Q')x=(len-read()),write(last=A[find(x)]),ENT;
33         else{
34             A[len]=(last+read())%mod;
35             while(top&&A[stack[~-top]]<=A[len])fa[stack[--top]]=len;
36             stack[top++]=len++;
37         }
38     }
39     return;
40 }
41 void work(){
42     return;
43 }
44 void print(){
45     return;
46 }
47 int main(){init();work();print();return 0;}

转载于:https://www.cnblogs.com/chxer/p/4644654.html

BZOJ 1012 [JSOI2008]最大数maxnumber相关推荐

  1. BZOJ 1012: [JSOI2008]最大数maxnumber 单调队列/线段树/树状数组/乱搞

    1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MB Submit: 4750  Solved: 2145 [Sub ...

  2. BZOJ 1012: [JSOI2008]最大数maxnumber

    1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MB Submit: 11358  Solved: 4978 [Su ...

  3. BZOJ 1012: [JSOI2008]最大数maxnumber(线段树)

    裸的线段树...因为数组开小了而一直RE..浪费了好多时间.. -------------------------------------------------------------------- ...

  4. 1012: [JSOI2008]最大数maxnumber

    1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MB Submit: 10711  Solved: 4683 [Su ...

  5. 【BZOJ】1012: [JSOI2008]最大数maxnumber 树状数组求区间最值

    题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1012 题意:维护一个数列,开始时没有数值,之后会有两种操作, Q L :查询数列末 ...

  6. 1012: [JSOI2008]最大数maxnumber 线段树

    https://www.lydsy.com/JudgeOnline/problem.php?id=1012 现在请求你维护一个数列,要求提供以下两种操作:1. 查询操作.语法:Q L 功能:查询当前数 ...

  7. 【BZOJ 1012】[JSOI2008]最大数maxnumber

    1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec Memory Limit: 162 MB Description 现在请求你维护一个数列,要求提供以下两种 ...

  8. BZOJ-1012[JSOI2008]最大数maxnumber 线段树区间最值

    这道题相对简单下面是题目: 1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec Memory Limit: 162 MB Submit: 6542 Solve ...

  9. 【bzoj1012】[JSOI2008]最大数maxnumber st表

    Description 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作.语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值.限制:L不超过当前数列的长度. 2. ...

最新文章

  1. 「镁客早报」任正非称对苹果等对手出售5G芯片持开放态度;马斯克称未来12个月内将生产超过50万辆车...
  2. 一加nfc门禁卡录入_忘记门禁卡不再徘徊 一加7T多功能NFC过来拯救你
  3. Activiti中的关于子流程中的并发节点标记处理
  4. Python --- 卸载
  5. (王道408考研数据结构)第二章线性表-第三节5:顺序表和链表的比较
  6. flask 接口上传文件_Flask干货:Flask数据交换——上传文件
  7. Photoshop和WPF双剑配合,打造炫酷个性的进度条控件
  8. Python-读取本地视频转化为图片方法记录(一)
  9. 【git】git的删除命令与如何删除仓库文件的方法
  10. python将一句话重复n次输出_在Python中创建单项重复n次的列表
  11. 前端判断是微信浏览器还是qq还是微信浏览器
  12. 6 计算机网络 待更新
  13. ubuntu14.04安装nvidia-GTK-1060驱动后黑屏
  14. 白领的一天 场景7:薪水与福利
  15. OpenGL入门:窗口开启、改变窗口背景颜色
  16. TensorFlow及深度学习相关资料积累汇总【不定期更新】
  17. 千里之行始于足下 | 开篇 - 增长极客
  18. C++类和对象介绍(筑基上篇)
  19. 【动画】css实现旋转和平移效果
  20. Ubuntu16.04+1080ti显卡驱动安装流程+循环登录问题【集锦】

热门文章

  1. can not open file Permission denied at securecrt_linux_crack.pl line 57
  2. Flink SQL Client的datagen的用法(转载+自己验证)
  3. 一些没啥用的大数据组件以及理由(持续更新中)+2020的Gartner曲线
  4. Gauss-Newton算法代码详细解释(转载+自己注释)
  5. A little something to get you started
  6. NLTK频率分类中定义的函数
  7. opengl glad.h和 glu.h
  8. 图像工程 CH6图像校正和修补
  9. ROS总结一,catkin,package,CMakeList,Topic,node
  10. 窗体测试只能用于本地测试_爆料:微软 Win10X 将首先用于测试单屏笔记本