洛谷 P1198 [JSOI2008]最大数
洛谷 P1198 [JSOI2008]最大数
题目描述
现在请求你维护一个数列,要求提供以下两种操作:
1、 查询操作。
语法:Q L
功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值。
限制:LL不超过当前数列的长度。(L > 0)(L>0)
2、 插入操作。
语法:A n
功能:将nn加上tt,其中tt是最近一次查询操作的答案(如果还未执行过查询操作,则t=0t=0),并将所得结果对一个固定的常数DD取模,将所得答案插入到数列的末尾。
限制:nn是整数(可能为负数)并且在长整范围内。
注意:初始时数列是空的,没有一个数。
输入格式
第一行两个整数,MM 和 DD,其中 MM 表示操作的个数,DD 如上文中所述。
接下来的 MM 行,每行一个字符串,描述一个具体的操作。语法如上文所述。
输出格式
对于每一个查询操作,你应该按照顺序依次输出结果,每个结果占一行。
题解:
抄的树状数组题解。
代码:
#include<bits/stdc++.h>
const int maxn = 2e5+7 ;
#define lowbit(x) (x & (-x))
using namespace std ;
int n,mod;
int T,tot;
int num[maxn];
int t[maxn] ;
inline int query(int l , int r)
{
int ans = 0;
while(l <= r)
{
ans = max(ans , num[r]) ;
for(--r ; r-l >= lowbit(r) ; r-=lowbit(r))
ans = max(ans,t[r]);
}
return ans ;
}
inline void add(int x)
{
num[++tot] = (x+T)%mod;
t[tot] = max(num[tot],query(tot+1-lowbit(tot) , tot-1));
}
int main()
{
scanf("%d%d",&n,&mod);
while(n--)
{
char in;
int x;
cin >> in;
scanf("%d",&x);
if(in == 'A') add(x);
else printf("%d\n",T=query(tot+1-x,tot));
}
return 0;
}