BZOJ 1012: [JSOI2008]最大数maxnumber

    xiaoxiao2025-02-02  0

    题目描述

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

    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 100 A 96 Q 1 A 97 Q 1 Q 2

    输出样例#1: 96 93 96


    线段树 建树,把初值赋成负无穷大。 其他的也就和普通线段树差不多。 注意 在洛谷负无穷只能赋成INT_MIN.


    #include<iostream> #include<climits> #include<cstdio> using namespace std; int m,d,lst,cnt; struct data { int l,r,mx; }a[900001]; void build(int num,int l,int r) { a[num].l=l; a[num].r=r; a[num].mx=INT_MIN; if(l==r) return ; int mid=l+r>>1; build(2*num,l,mid); build(2*num+1,mid+1,r); } void insert(int num,int l,int r,int cur,int x) { a[num].mx=max(a[num].mx,x); if(l==r) return ; int mid=l+r>>1; if(mid>=cur) insert(2*num,l,mid,cur,x); else insert(2*num+1,mid+1,r,cur,x); } int query(int num,int l,int r) { if(a[num].l>r||a[num].r<l) return INT_MIN; if(a[num].l>=l&&a[num].r<=r) return a[num].mx; return max(query(2*num,l,r),query(2*num+1,l,r)); } int main() { scanf("%d%d",&m,&d); build(1,1,m); for(int i=1;i<=m;i++) { int x; char c[11]; scanf("%s%d",c,&x); if(c[0]=='A') { cnt++; x=(x+lst)%d; insert(1,1,m,cnt,x); } else { lst=query(1,cnt-x+1,cnt); printf("%d\n",lst); } } return 0; }
    转载请注明原文地址: https://ju.6miu.com/read-1296009.html
    最新回复(0)