洛谷 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
",T=query(tot+1-x,tot));
	}
	return 0;
}
原文地址:https://www.cnblogs.com/fusiwei/p/14037678.html