[BZOJ 1012][JSOI2008]最大数maxnumber(线段树)

Description

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

Solution

一开始把空的地方都建出来,记一下当前的序列长度,然后就可以进行普通的线段树操作了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#define Max(a,b) (a>b?a:b)
#define MAXN 200005
using namespace std;
int m,tot=0;
long long d,last=0;
struct Node{
    int l,r;
    long long maxn;
}t[MAXN*4];
void build(int idx,int l,int r)
{
    t[idx].l=l,t[idx].r=r;
    if(l==r)return;
    int mid=(l+r)>>1;
    build(idx<<1,l,mid);
    build(idx<<1|1,mid+1,r);
}
void add(int idx,int a,long long b)
{
    if(t[idx].l==t[idx].r)
    {t[idx].maxn=b;return;}
    int mid=(t[idx].l+t[idx].r)>>1;
    if(a<=mid)add(idx<<1,a,b);
    else add(idx<<1|1,a,b);
    t[idx].maxn=Max(t[idx<<1].maxn,t[idx<<1|1].maxn);
}
long long query(int idx,int a,int b)
{
    if(t[idx].l>=a&&t[idx].r<=b)
    return t[idx].maxn;
    int mid=(t[idx].l+t[idx].r)>>1;
    if(b<=mid)return query(idx<<1,a,b);
    else if(a>mid)return query(idx<<1|1,a,b);
    else return Max(query(idx<<1,a,b),query(idx<<1|1,a,b));
}
int main()
{
    scanf("%d%lld",&m,&d);
    build(1,1,m);
    for(int i=1;i<=m;i++)
    {
        char opt;
        int x;long long t;
        opt=getchar();
        while(opt!='Q'&&opt!='A')
        opt=getchar();
        scanf("%d",&x);
        if(opt=='Q')
        {
            last=query(1,tot-x+1,tot);
            printf("%lld\n",last);
        }
        else if(opt=='A')
        {
            t=(last+x)%d;
            add(1,tot+1,t);
            tot++;
        }
    }
    return 0;
}

 

posted @ 2017-03-31 23:10  Zars19  阅读(280)  评论(0编辑  收藏  举报