您的位置:首页 > Web前端 > JavaScript

BZOJ 1012 [JSOI2008] 最大数 maxnumber 题解&代码

2015-12-03 19:18 691 查看
题目简洁明了= =我就不详细说了,线段树最大值裸题

维护一个数列,要求提供以下两种操作:

1、 查询操作。语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值。

限制:L不超过当前数列的长度。

2、 插入操作。语法:A n 功能:将n加上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取模,将所得答案插入到数列的末尾。

限制:n是非负整数并且在长整范围内。注意:初始时数列是空的,没有一个数。

**注意long long

思路就是假设这个线段树全部都是插入操作= =于是线段树最大只有m个元素,这样就把问题简化为

1、查询区间[tot-L,tot-1]的最大值(tot是当前元素总数+1)

2、将tot处的元素修改为(n+t)%d

初始化线段树时所有元素均为0

线段树求区间最大值问题= =代码量不算大,属于简单线段树

/**************************************************************
Problem: 1012
User: Rainbow6174
Language: C++
Result: Accepted
Time:1232 ms
Memory:15336 kb
****************************************************************/

#include<iostream>
#include<stdio.h>
using namespace std;
char c[5];
int m,q,a,b,tot;
long long MOD,ans,x,n,val[200005],add[800020],maxn[800020];
void maintain(int o,int l,int r)
{
if(l!=r)
maxn[o]=max(maxn[o<<1],maxn[(o<<1)+1]);
else maxn[o]=val[l];
}
void addnum(int o,int l,int r)
{
if(l>=a && r<=b)
{
maxn[o]=val[a]=x;
return;
}
if(r<a || l>b)return;
int mid=(l+r)/2;
addnum(o<<1,l,mid);
addnum((o<<1)+1,mid+1,r);
maintain(o,l,r);
return;
}
void getmax(int o,int l,int r)
{
if(l>=a && r<=b)
{
ans=max(ans,maxn[o]);
return;
}
if(r<a || l>b)return;
int mid=(l+r)/2;
getmax(o<<1,l,mid);
getmax((o<<1)+1,mid+1,r);
maintain(o,l,r);
return;
}
int main(void)
{
scanf("%d%lld",&m,&MOD);
tot=1;
for(int i=1;i<=m;i++)
{
scanf("%s%lld",&c,&n);
if(c[0]=='A')
{
x=(ans+n)%MOD;
a=tot;b=tot;
addnum(1,1,m);
tot++;
}
else
{
ans=0;
a=tot-n;
b=tot-1;
getmax(1,1,m);
printf("%lld\n",ans);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: