BZOJ 1012 JSOI 2008 最大数 maxnumber 线段树水题

题目大意:维护一种数据结构,支持两个功能:查询区间最大,插入到数列的最后。


思路:一眼就看到是线段树了,没什么好说的。只有一点要注意,插入的时候线段树的范围不要跟着序列中的总数走,那样建完节点之后无法更新父亲节点的信息。


CODE:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 200010
#define MO d
#define LEFT (pos << 1)
#define RIGHT (pos << 1|1)
using namespace std;

int cnt,asks,d;
int tree[MAX << 2];
int last;

char c[10];

void Modify(int l,int r,int aim,int pos,int c);
int Ask(int l,int r,int x,int y,int pos);

int main()
{
	cin >> asks >> d;
	for(int x,i = 1;i <= asks; ++i) {
		scanf("%s",c);
		switch(c[0]) {
			case 'Q':
				scanf("%d",&x);
 				last = Ask(1,MAX - 1,cnt - x + 1,cnt,1);
				printf("%d\n",last);
				break;
			case 'A':
				cnt++;
				scanf("%d",&x);
				Modify(1,MAX - 1,cnt,1,(x + last) % MO);
				break;
		}
	}
	return 0;
}

void Modify(int l,int r,int aim,int pos,int c)
{
	if(l == r) {
		tree[pos] = c;
		return ;
	}
	int mid = (l + r) >> 1;
	if(aim <= mid)	Modify(l,mid,aim,LEFT,c);
	else	Modify(mid + 1,r,aim,RIGHT,c);
	tree[pos] = max(tree[LEFT],tree[RIGHT]);
}

int Ask(int l,int r,int x,int y,int pos)
{
	if(l == x && r == y)	return tree[pos];
	int mid = (l + r) >> 1;
	if(y <= mid)	return Ask(l,mid,x,y,LEFT);
	if(x > mid)		return Ask(mid + 1,r,x,y,RIGHT);
	int left = Ask(l,mid,x,mid,LEFT);
	int right = Ask(mid + 1,r,mid + 1,y,RIGHT);
	return max(left,right); 
}



你可能感兴趣的:(数据结构,线段树,bzoj,BZOJ1012)