又一道非常简单的线段树入门题
先看题

题目描述

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

输入输出格式

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

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

输入输出样例

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

输出样例#1:
96
93
96

这道题唯一的特殊性就在于,元素最初未给出,塞进去的元素跟后续运算结果有关,由于元素个数起初也不确定,所以这是唯一特殊的地方
对于这种特殊,我们的处理方法就是,在建树时,直接将长度尽可能建的大一些,剩下就是纯线段树的模板了

但是,这道题数据有问题,自己写快读会WA,一定要用scanf

下放代码

#include<iostream>
#include<cstdio>
#include<cctype>
#define ll long long
#define gc() getchar()
#define maxn 200005
using namespace std;

int n,m;
ll a[maxn],q,g;
inline ll read(){    //朴素的快读
    ll a=0;int f=1;char p=gc();
    while(!isdigit(p)){f|=(p=='-');p=gc();}
    while(isdigit(p)){a=(a<<3)+(a<<1)+(p^48);p=gc();}
    return a*f;
}

struct ahaha{
    ll v;
}t[maxn<<2];
#define lc p<<1
#define rc p<<1|1
inline void pushup(int p){    //朴素的上传
    t[p].v=max(t[lc].v,t[rc].v);
}
void build(int p,int l,int r){     //朴素的建树
    if(l==r){t[p].v=-100000000;return;}
    int m=l+r>>1;
    build(lc,l,m);build(rc,m+1,r);
    pushup(p);
}
void update(int p,int l,int r,int L,ll z){    //朴素的更新
    if(l>L||r<L)return;
    if(l==r&&r==L){t[p].v=z;return;}
    int m=l+r>>1;
    update(lc,l,m,L,z);update(rc,m+1,r,L,z);
    pushup(p);
}
ll query(int p,int l,int r,int L,int R){   //朴素的查询
    if(l>R||r<L)return -100000000;
    if(L<=l&&r<=R)return t[p].v;
    int m=l+r>>1;
    return max(query(lc,l,m,L,R),query(rc,m+1,r,L,R));
}

inline void solve_1(){
    int x;++n;scanf("%d",&x);
    update(1,1,maxn-5,n,(x+q)%g);    //新的元素取模后塞入即可
}
inline void solve_2(){
    int x;scanf("%d",&x);
    if(x==0){printf("0\n");return;}
    q=query(1,1,maxn-5,n-x+1,n);
    printf("%lld\n",q);
}

int main(){
    //m=read();g=read();
    scanf("%d%d",&m,&g);
    build(1,1,maxn-5);
    for(int i=1;i<=m;++i){
        char zz[100];
        scanf("%s",zz);
        switch(zz[0]){
            case 'A':solve_1();break;
            case 'Q':solve_2();break;
        }
    }
    return 0;
}