BZOJ 1012: [JSOI2008]最大数maxnumber

现在请求你维护一个数列,要求提供以下两种操作: 1、 查询操作。 语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值。 限制:L不超过当前数列的长度。 2、 插入操作。 语法:A n 功能:将n加上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取模,将所得答案插入到数列的末尾。 限制:n是非负整数并且在长整范围内。 注意:初始时数列是空的,没有一个数。

 http://www.lydsy.com/JudgeOnline/problem.php?id=1012

/*
* 分析:
* 单调队列加暴力。
* 这个程序优化的地方:可以只存标号,每次Q操作的时候直接二分。
* */

#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

const int X = 200005;

struct node{
	int id,val;
}q[X];

int main(){
	int n,m;
	while(cin>>n>>m){
		int pre = 0;
		int x;
		char op[2];
		int head = 0,tail = 0;
		int len = 0;
		for(int i=1;i<=n;i++){
			scanf("%s%d",op,&x);
			if(op[0]=='A'){
				x = (x+pre)%m;
				while(tail&&q[tail-1].val<=x)
					tail --;
				q[tail].val = x;
				q[tail++].id = ++len;
			}
			else{
				for(int j=tail-1;j>=0;j--){
					if(q[j].id+x<=len)
						break;
					else
						pre = q[j].val;
				}
				printf("%d\n",pre);
			}
		}
	}
	return 0;
}

  

第二种方法:

/*
* 分析:
* 建立线段树
* 对于A操作,只需要update一下
* 对于Q操作,只需要query一下就好了。。
*
* */

#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

const int X = 200002;

#define debug puts("here");

struct seg_tree{
	int l,r;
	int val;
	int mid(){
		return (l+r)>>1;
	}
}tree[X<<2];

void build(int l,int r,int rt){
	tree[rt].l = l;
	tree[rt].r = r;
	if(l==r)
		return;
	int mid = tree[rt].mid();
	build(l,mid,rt<<1);
	build(mid+1,r,rt<<1|1);
}

void update(int pos,int val,int rt){
	if(tree[rt].l==tree[rt].r){
		tree[rt].val = val;
		return;
	}
	int mid = tree[rt].mid();
	if(mid>=pos)
		update(pos,val,rt<<1);
	else
		update(pos,val,rt<<1|1);
	tree[rt].val = max(tree[rt<<1].val,tree[rt<<1|1].val);
}

int query(int l,int r,int rt){
	if(l<=tree[rt].l&&r>=tree[rt].r)
		return tree[rt].val;
	int mid = tree[rt].mid();
	int ans = 0;
	if(l<=mid)
		ans = max(ans,query(l,r,rt<<1));
	if(r>mid)
		ans = max(ans,query(l,r,rt<<1|1));
	return ans;
}

int main(){
	int n,m;
	while(cin>>n>>m){
		char op[2];
		int x;
		int pre = 0;
		int len = 0;
		build(1,n,1);
		while(n--){
			scanf("%s%d",op,&x);
			if(op[0]=='A')
				update(++len,(pre+x)%m,1);
			else{
				pre = query(len-x+1,len,1);
				printf("%d\n",pre);
			}
		}
	}
	return 0;
}

  

原文地址:https://www.cnblogs.com/yejinru/p/2824906.html