Problem Specification Value
Time Limit 3 Sec
Memory Limit 162 MB
Submit 7661
Solved 3303

Description

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

Input

第一行两个整数, M 和 D, 其中 M 表示操作的个数 (M <=200, 000), D 如上文中所述, 满足 D 在 longint 内. 接下来 M 行, 查询操作或者插入操作.

Output

对于每一个询问操作, 输出一行. 该行只有一个数, 即序列中最后 L 个数的最大数.

Sample Input

5 100
A 96
Q 1
A 97
Q 1
Q 2

Sample Output

96
93
96

HINT

数据如下 http: //pan. baidu. com/s/1i4JxCH3

Source


这道题可以直接用线段树水过......

而且因为并不需要对整个区间进行操作所以change 函数也可以写成自底向上的线段树...... 同时 change 就不需要写成区间修改了.

然而为什么我的代码和 hzwer 的代码对拍了很久还是没有 AC (和他的结果一模一样但是就是不能通过 bzoj, 再者百度盘上的也都测过没问题~


为了让 Atom 不要把_n, __n, ___n 都识别成斜体和粗体害的我把所有_n 都加上了四个下划线 233


#include <iostream>
#include <cstdlib>
#include <cstdio>

using namespace std;
typedef long long ll;
const int maxn = 800100;
const ll inf = 0x3f3f3f3f3f3f3f3fll;

class SegmentTree
{
public:
    int pwn, n, lb[maxn], rb[maxn];
    ll mn[maxn];
    void build_tree(int ____n)
    {
        // An optimized segment tree which abandons all unused functions in this problem
        n = 0; pwn = 1; while (pwn < ____n) pwn <<= 1;
        ____n = pwn;
        for (int i = ____n; i <= ____n * 2 - 1; i++) {
            lb[i] = rb[i] = i - ____n + 1;
            mn[i] = inf;
        }
        for (int i = ____n - 1; i >= 1; i--) {
            lb[i] = lb[2 * i];
            rb[i] = rb[2 * i + 1];
            mn[i] = inf;
        }
        return ;
    }
    void append(ll v)
    {
        int p = pwn + n;
        mn[p] = v;
        p >>= 1;
        while (p) {
            mn[p] = max(mn[2 * p], mn[2 * p + 1]);
            p >>= 1;
        }
        n++;
        return ;
    }
    ll query(int p, int l, int r)
    {
        if (lb[p] == l && rb[p] == r)
            return mn[p];
        if (r <= rb[2 * p])
            return query(2 * p, l, r);
        if (l >= lb[2 * p + 1])
            return query(2 * p + 1, l, r);
        return max(query(2 * p, l, rb[2 * p]),
                query(2 * p + 1, lb[2 * p + 1], r));
    }
    ll query(int d)
    {
        return query(1, max(1, n + 1 - d), n);
    }
} st;

int m, D, t = 0;

int main(int argc, char** argv)
{
    scanf("%d%lld", &m, &D);
    st.build_tree(m);
    for (int i = 1; i <= m; i++) {
        char c[100];
        ll v;
        scanf("%s%lld", &c, &v);
        if (c[0] == 'A') {
            st.append((t + v) % D);
        } else if (c[0] == 'Q') {
            t = st.query(v);
            printf("%lld\n", t);
        }
    }
    return 0;
}

这是 hzwer AC 的代码:

#include<iostream>
#include<cstdio>
#define inf 0x7fffffff
using namespace std;
int m,mod,last,cnt;
struct data{int l,r,mx;}t[800005];
void build(int k,int l,int r)
{
    t[k].l=l;t[k].r=r;t[k].mx=-inf;
    if(l==r)return;
    int mid=(l+r)>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
}
int ask(int k,int x,int y)
{
    int l=t[k].l,r=t[k].r;
    if(l==x&&r==y)return t[k].mx;
    int mid=(l+r)>>1;
    if(y<=mid)return ask(k<<1,x,y);
    else if(x>mid)return ask(k<<1|1,x,y);
    else return max(ask(k<<1,x,mid),ask(k<<1|1,mid+1,y));
}
void insert(int k,int x,int y)
{
    int l=t[k].l,r=t[k].r;
    if(l==r){t[k].mx=y;return;}
    int mid=(l+r)>>1;
    if(x<=mid)insert(k<<1,x,y);
    else insert(k<<1|1,x,y);
    t[k].mx=max(t[k<<1].mx,t[k<<1|1].mx);
}
int main()
{
    scanf("%d%d",&m,&mod);
    build(1,1,m);
    for(int i=1;i<=m;i++)
    {
        char ch[5];scanf("%s",ch);
        int x;
        if(ch[0]=='A')
        {
            cnt++;
            scanf("%d",&x);x=(x+last)%mod;
            insert(1,cnt,x);
        }
        else
        {
            scanf("%d",&x);
            last=ask(1,cnt-x+1,cnt);
            printf("%d\n",last);
        }
    }
    return 0;
}

from pydatagen import *
a = randrange(3, 200000)
d = randrange(964, 1047483000)
printf('%d %d\n' % (a, d))
printf('A %d\n' % randrange(1, 1047483647))
sz = 1
for i in range(1, a):
    q = choice(['A', 'Q'])
    if q == 'Q':
        printf('Q %d\n' % randrange(1, sz + 1))
    elif q == 'A':
        printf('A %d\n' % randrange(1, 1047483647))
fclose()