【UOJ 52】最大数
【题目描述】:
现在请求你维护一个数列,要求提供以下两种操作:
1、 查询操作。
语法:Q L
功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值。
限制:L不超过当前数列的长度。
2、 插入操作。
语法:A n
功能:将n加上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取模,将所得答案插入到数列的末尾。限制:n是整数(可能为负数)并且在int范围内。(先加再取模)
注意:初始时数列是空的,没有一个数。
【输入描述】:
第一行两个整数,M和D,其中M表示操作的个数,D如上文中所述
接下来的M行,每行一个字符串,描述一个具体的操作。语法如上文所述。
【输出描述】:
对于每一个查询操作,你应该按照顺序依次输出结果,每个结果占一行。
【样例输入】:
5 100
A 96
Q 1
A 97
Q 1
Q 2
【样例输出】:
96
93
96
【时间限制、数据范围及描述】:
时间:1s 空间:128M
M <= 200,000; 0 < D < 2,000,000,000
题解:普通线段树%
#include<cstdio> #include<iostream> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> #include<bits/stdc++.h> typedef long long ll; using namespace std; const int N=200002; int last,n; int T,mod,a,add[N*4],mx[N*4]; void pushup(int rt) { mx[rt]=max(mx[rt*2],mx[rt*2+1])%mod; } int query(int L,int R,int l,int r,int rt){ if(l>R||r<L)return -(1<<30); if(L<=l && r<=R) return mx[rt]; int m=(l+r)/2; // pushdown(rt); int ans=-0x3f3f3f3f; if(L<=m) ans=max(ans,query(L,R,l,m,rt*2)); if(R>m) ans=max(ans,query(L,R,m+1,r,rt*2+1)); return ans; } void update(int L,int R,int c,int l,int r,int rt){ //printf("%d %d\n",l,r); if(l>R||r<L)return; if(l==r){ mx[rt]=(c)%mod; //add[rt]=(add[rt]+c); return ; } int m=(l+r)/2; // pushdown(rt); if(L<=m) update(L,R,c,l,m,rt*2); else update(L,R,c,m+1,r,rt*2+1); pushup(rt); } char cc; int x; int main(){ //freopen("52.in","r",stdin); //freopen("52.out","w",stdout); cin>>T>>mod; memset(mx,128,sizeof(mx)); //for(int i=1;i<=4*N;i++) // mx[i]=-0x3f3f3f3f; for(int i=1;i<=T;i++){ cin>>cc>>x; //cout<<x<<endl; if(cc=='Q'){ last=query(n-x+1,n,1,T,1); printf("%d\n",last%mod); //cout<<"ck2:"<<query(1,1,1,n,1)<<endl; } if(cc=='A'){ n++; //cout<<"____"<<n<<"_____"<<last+x<<endl; //cout<<(last+x); //cout<<n //printf("%d\n",(last+x)%mod); update(n,n,(last+x)%mod,1,T,1); //cout<<"ck1:"<<query(1,1,1,n,1)<<endl; //cout<<query(1,1,1,n,1)<<endl; } //cout<<n; } //cout<<query(1,1,1,n,1)<<' '<<query(2,2,1,n,1); return 0; }