博客园 首页 私信博主 显示目录 隐藏目录 管理 动画

洛谷P1198 [JSOI2008]最大数(BZOJ.1012 )

To 洛谷.1198 最大数

题目描述

现在请求你维护一个数列,要求提供以下两种操作:

1、 查询操作。

语法:Q L

功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值。

限制:L不超过当前数列的长度。

2、 插入操作。

语法:A n

功能:将n加上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取模,将所得答案插入到数列的末尾。

限制:n是整数(可能为负数)并且在长整范围内。

注意:初始时数列是空的,没有一个数。

输入输出格式

输入格式:

 

第一行两个整数,M和D,其中M表示操作的个数(M <= 200,000),D如上文中所述,满足(0<D<2,000,000,000)

接下来的M行,每行一个字符串,描述一个具体的操作。语法如上文所述。

 

输出格式:

 

对于每一个查询操作,你应该按照顺序依次输出结果,每个结果占一行。

 

输入输出样例

输入样例#1:
5 100
A 96
Q 1
A 97
Q 1
Q 2
输出样例#1:
96
93
96

说明

[JSOI2008]

 思路:

  1.线段树。在初始建树时将所有节点赋值为-INF,操作和单点修改与区间最值并没有多少不同。

  2.单调队列+二分查找。

代码:

1.线段树  722ms/17.06MB,比方法2要慢近一倍。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define LL long long
 4 using namespace std;
 5 const int N=200005,INF=1e9+10;
 6 
 7 int m,mod,len;
 8 LL t,Max[N<<2];
 9 
10 void read(int &now)
11 {
12     now=0;bool f=0;char c=getchar();
13     while(c<'0'||c>'9')
14     {
15         if(c=='-')f=1;
16         c=getchar();
17     }
18     while(c>='0'&&c<='9')now=(now<<3)+(now<<1)+c-'0',c=getchar();
19     now= f?-now:now;
20 }
21 
22 void PushUp(int rt)
23 {
24     Max[rt]= Max[rt<<1]<Max[rt<<1|1]?Max[rt<<1|1]:Max[rt<<1];
25 }
26 
27 void Build(int l,int r,int rt)
28 {
29     if(l==r)
30     {
31         Max[rt]=-INF;
32         return;
33     }
34     int m=(l+r)>>1;
35     Build(l,m,rt<<1);
36     Build(m+1,r,rt<<1|1);
37     PushUp(rt);
38 }
39 
40 void ModifyPoint(int l,int r,int rt,int p,int v)
41 {
42     if(l==r)
43     {
44         Max[rt]= Max[rt]<v?v:Max[rt];
45         return;
46     }
47     int m=(l+r)>>1;
48     if(p<=m) ModifyPoint(l,m,rt<<1,p,v);
49     else ModifyPoint(m+1,r,rt<<1|1,p,v);
50     PushUp(rt);
51 }
52 
53 LL QueryMax(int l,int r,int rt,int L,int R)
54 {
55     if(L<=l && r<=R) return Max[rt];
56     int m=(l+r)>>1;
57     LL res=-INF;
58     if(L<=m) res=max(res,QueryMax(l,m,rt<<1,L,R));
59     if(m<R) res=max(res,QueryMax(m+1,r,rt<<1|1,L,R));
60     return res;
61 }
62 
63 int main()
64 {
65     read(m);read(mod);
66     Build(1,m,1);
67     for(int i=1;i<=m;++i)
68     {
69         char opt[5];int num;
70         scanf("%s",opt);read(num);
71         if(opt[0]=='A')
72           ModifyPoint(1,m,1,++len,(num+t)%mod);
73         else
74           printf("%lld\n",t=QueryMax(1,m,1,len-num+1,len));
75     }
76     return 0;
77 }
线段树(插入元素 区间最值)

2.单调队列+lower_bound(+栈) 337ms/12.6MB

(先写 if(opt[0]=='Q')+询问 后写插入 就会错是什么鬼。。 哪位dalao看出来帮我指出一下。。thanks)

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 const int N=200005;
 5 
 6 int m,mod,len,size,t,Num[N],Stack[N];
 7 
 8 void read(int &now)
 9 {
10     now=0;bool f=0;char c=getchar();
11     while(c<'0'||c>'9')
12     {
13         if(c=='-')f=1;
14         c=getchar();
15     }
16     while(c>='0'&&c<='9')now=(now<<3)+(now<<1)+c-'0',c=getchar();
17     now= f?-now:now;
18 }
19 
20 /*int Mylower_bound(int s,int t,int p)
21 {
22     int l=s,r=t,m;
23     while(l<r)
24     {
25         m=(l+r)>>1;
26         if(Stack[m]<p)
27           l=m+1;
28         else if(Stack[m]==p)
29           return m;
30         else
31           r=m;
32     }
33     return l;
34 }*/
35 
36 int main()
37 {
38     read(m);read(mod);
39     char opt[5];int a;
40     while(m--)
41     {
42         scanf("%s",opt);read(a);
43         if(opt[0]=='A')
44         {//因为比当前元素小的数在最后的求最大值中毫无作用,所以直接弹出 
45             a=(a+t)%mod;
46             Num[++len]=a;
47             while(size && Num[Stack[size]]<=a)
48               --size;
49             Stack[++size]=len;
50         }
51         else
52         {//Stack[i]存储的是一个位置pos,且这些位置单调递增,这些位置对应的Num[pos]也单调递增 
53             int pos=lower_bound(Stack+1,Stack+size+1,len-a+1)-Stack;//找出一个Stack中大于等于查询位置的pos 
54             //int pos=Mylower_bound(1,size,len-a+1);
55             printf("%d\n",t=Num[Stack[pos]]);
56         }
57     }
58     return 0;
59 }
单调队列

 错误的写法

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 const int N=200005;
 5 
 6 int m,mod,len,size,t,Num[N],Stack[N];
 7 
 8 void read(int &now)
 9 {
10     now=0;bool f=0;char c=getchar();
11     while(c<'0'||c>'9')
12     {
13         if(c=='-')f=1;
14         c=getchar();
15     }
16     while(c>='0'&&c<='9')now=(now<<3)+(now<<1)+c-'0',c=getchar();
17     now= f?-now:now;
18 }
19 
20 int main()
21 {
22     read(m);read(mod);
23     char opt[5];int a;
24     while(m--)
25     {
26         scanf("%s",opt);read(a);
27         if(opt[0]=='Q')
28         {//Stack[i]存储的是一个位置,且这些位置单调递增,这些位置对应的Num[pos]也单调递增 
29             int pos=lower_bound(Stack+1,Stack+size+1,len-a+1)-Stack;
30             printf("%d\n",t=Num[pos]);
31         }
32         else
33         {//因为比当前元素小的数在最后的求最大值中毫无作用,所以直接弹出 
34             a=(a+t)%mod;
35             Num[++len]=a;
36             while(size && Num[Stack[size]]<=a)
37               --size;
38             Stack[++size]=len;
39         }
40     }
41     return 0;
42 }
0分

 

posted @ 2017-05-23 19:24  SovietPower  阅读(175)  评论(0编辑  收藏  举报