洛谷1198最大数(线段树)

来源:互联网 发布:破解网络 编辑:程序博客网 时间:2024/06/06 07:48

题目描述

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

输入输出格式

输入格式:

第一行两个整数,M和D,其中M表示操作的个数(M <= 200,000),D如上文中所述,满足(0<D<2,000,000,000)
接下来的M行,每行一个字符串,描述一个具体的操作。语法如上文所述。

输出格式:

对于每一个查询操作,你应该按照顺序依次输出结果,每个结果占一行。

输入输出样例

输入样例#1:
5 100A 96Q 1A 97Q 1Q 2
输出样例#1:
969396

说明

[JSOI2008]

洛谷ac

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <cmath>#include <cctype>#define ll intusing namespace std;const int maxn=800005;const ll inf=(ll)2147483648;ll _max[maxn],a[maxn],mod,ans=0,x;int m,p=0,ql,qr;inline ll get(){    char c;bool f=0;while(!isdigit(c=getchar()))if(c=='-')f=1;ll v=c-48;while(isdigit(c=getchar()))v=v*10+c-48; if(f)v=-v;return v;}inline void update(int node,int l,int r){    if(l==r)a[p]=_max[node]=x;    else{int mid=(l+r)>>1;    if(p<=mid)update((node<<1),l,mid);    else update((node<<1)+1,mid+1,r);_max[node]=max(_max[(node<<1)],_max[(node<<1)+1]);}}inline ll query(int node,int l,int r){ll mx=-inf;    if(ql<=l && qr>=r)mx=_max[node];    else{int mid=(l+r)>>1;    if(ql<=mid)mx=max(query((node<<1),l,mid),mx);    if(qr>mid)mx=max(query((node<<1)+1,mid+1,r),mx);}return mx;}int main(){    m=(int)get();mod=get();    for(int i=1;i<=m;++i){    char c;    scanf("%c",&c);    if(c=='A'){    ++p;    x=(int)get();     x=(x%mod+ans%mod)%mod;    update(1,1,m);}else{int l=(int)get();if(l<=0)continue;ql=p-l+1;qr=p;    ans=query(1,1,m);    printf("%d\n",ans);}}return 0;}


bzojac

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <cmath>#include <cctype>#define ll long longusing namespace std;const int maxn=800005;const ll inf=(ll)2147483648;ll _max[maxn],a[maxn],mod,ans=0,x;int m,p=0,ql,qr;inline ll get(){    char c;bool f=0;while(!isdigit(c=getchar()))if(c=='-')f=1;ll v=c-48;while(isdigit(c=getchar()))v=v*10+c-48; if(f)v=-v;return v;}inline void update(int node,int l,int r){    if(l==r)a[p]=_max[node]=x;    else{int mid=(l+r)>>1;    if(p<=mid)update((node<<1),l,mid);    else update((node<<1)+1,mid+1,r);_max[node]=max(_max[(node<<1)],_max[(node<<1)+1]);}}inline ll query(int node,int l,int r){ll mx=-inf;    if(ql<=l && qr>=r)mx=_max[node];    else{int mid=(l+r)>>1;    if(ql<=mid)mx=max(query((node<<1),l,mid),mx);    if(qr>mid)mx=max(query((node<<1)+1,mid+1,r),mx);}return mx;}int main(){    m=(int)get();mod=get();    for(int i=1;i<=m;++i){    char c;    scanf("%c",&c);    if(c=='A'){    ++p;    x=(int)get();     x=(x%mod+ans%mod)%mod;    update(1,1,m);}else{int l=(int)get();if(l<=0)continue;ql=p-l+1;qr=p;    ans=query(1,1,m);    printf("%lld\n",ans);}}return 0;}




思路:裸的线段树点修改;

注意:队列的位置和结点的区别。



0 0