[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如上文中所述,满足D在longint内。接下来
M行,查询操作或者插入操作。
Output
对于每一个询问操作,输出一行。该行只有一个数,即序列中最后L个数的最大数。
Sample Input
5 100
A 96
Q 1
A 97
Q 1
Q 2
A 96
Q 1
A 97
Q 1
Q 2
Sample Output
96
93
96
93
96
题解
这里提供两种做法,单调队列和线段树
先说一下线段树解法
一.线段树解法
首先看到这道题就能想到线段树吧
这道题的线段树代码也很容易打,毕竟都没有lazy标记,就是单纯的点修改
然后建树函数也可以不打的..这道题的插入其实就是一个建树的过程,如果不打建树函数的话代码前面memset一下-inf就好
下面是代码:
#include <cstdio> #include <cstring> #define ll long long #define inf 0x7fffffff #define il inline il ll max(ll x,ll y){return x>y?x:y;} il ll min(ll x,ll y){return x<y?x:y;} il ll abs(ll x){return x>0?x:-x;} il void swap(ll &x,ll &y){ll t=x;x=y;y=t;} il void read(ll &x){ x=0;ll f=1;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} x*=f; } using namespace std; /*===================Header Template=====================*/ #define N 200010 ll t[N<<2],n,mod,len=0,T=0; void update(ll L,ll c,ll l,ll r,ll rt){ if(l==r){t[rt]=c;return;} ll mid=(l+r)>>1; if(L<=mid)update(L,c,l,mid,rt<<1); else update(L,c,mid+1,r,rt<<1|1); t[rt]=max(t[rt<<1],t[rt<<1|1]); } ll query(ll L,ll R,ll l,ll r,ll rt){ if(L<=l&&R>=r)return t[rt]; ll mid=(l+r)>>1,ans=-inf; if(L<=mid)ans=max(ans,query(L,R,l,mid,rt<<1)); if(R>mid)ans=max(ans,query(L,R,mid+1,r,rt<<1|1)); return ans; } int main(){ memset(t,128,sizeof(t)); read(n);read(mod); for(ll i=1;i<=n;i++){ char c=getchar(); ll num;read(num); if(c=='A'){ len++; update(len,(num+T)%mod,1,n,1); }else { if(num){ T=query(len-num+1,len,1,n,1)%mod; printf("%lld\n",T); }else { printf("0\n"); T=0; } } } return 0; }
然而这道题是很玄学的,你把这个代码扔到洛谷上面会发现全部点MLE,然后在bzoj是能ac的...
如果要在洛谷提交就看一下我的代码理解一下思路自己试着打一个,或者说看看下面的单调队列写法
二.单调队列解法
单调队列的写法就很简单了,但是很难想到这个做法,毕竟如果学过线段树第一时间想到的也会是线段树吧
这里维护一下最大值就好
#include <cstdio> #include <cstring> #define ll int #define inf 1<<30 #define il inline il ll max(ll x,ll y){return x>y?x:y;} il ll min(ll x,ll y){return x<y?x:y;} il ll abs(ll x){return x>0?x:-x;} il void swap(ll &x,ll &y){ll t=x;x=y;y=t;} il void read(ll &x){ x=0;ll f=1;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} x*=f; } using namespace std; /*===================Header Template=====================*/ #define N 200010 ll mx[N],a[N],p,m,mod,t,l=0; char c[1]; int main(){ read(m);read(mod); while(m--){ scanf("%s%d",c,&p); if(c[0]=='A'){ a[++t]=(l+p)%mod; for(ll i=t;i;i--){ if(mx[i]<a[t])mx[i]=a[t]; else break; } }else printf("%d\n",l=mx[t-p+1]); } return 0; }
转载请注明出处:https://www.cnblogs.com/henry-1202/p/9090699.html