【JSOI2008】最大数

https://www.luogu.org/problem/show?pid=1198

之前刚学完Splay想找题练手的时候做的,写完Splay交上去了才发现这应该是线段树裸题23333

Splay解法

按照要求操作即可……

#include <iostream>
using namespace std;
int m, d, t;
const int inf = 0x7fffffff;
namespace splay
{
struct node;
node *nil = 0, *root;
struct node
{
    int val, size, maxnum;
    node *ch[2];
    node(int v) : val(v), size(1), maxnum(v)
    {
        ch[0] = ch[1] = nil;
    }
    void pull_up()
    {
        size = ch[0]->size + ch[1]->size + 1;
        maxnum = max(val, max(ch[0]->maxnum, ch[1]->maxnum));
    }
    int cmp(int k)
    {
        if(this == nil || k == ch[0]->size + 1)
            return -1;
        else
            return (k <= ch[0]->size) ? 0 : 1;
    }
};
void init()
{
    if(!nil)
        nil = new node(-inf);
    nil->size = 0;
    nil->ch[0] = nil->ch[1] = nil;
    root = new node(-inf);
    root->ch[1] = new node(-inf);
    root->size = 2;
}
void rotate(node *&t, int d)
{
    node *k = t->ch[d ^ 1];
    t->ch[d ^ 1] = k->ch[d];
    k->ch[d] = t;
    t->pull_up();
    k->pull_up();
    t = k;
}
void splay(int k, node *&t = root)
{
    int d1 = t->cmp(k);
    if(d1 == 1)
        k = k - t->ch[0]->size - 1;
    if(d1 != -1)
    {
        int d2 = t->ch[d1]->cmp(k);
        if(d2 != -1)
        {
            int k2 = (d2 == 1) ? (k - t->ch[d1]->ch[0]->size - 1) : k;
            splay(k2, t->ch[d1]->ch[d2]);
            if(d1 != d2)
            {
                rotate(t->ch[d1], d2 ^ 1);
                rotate(t, d1 ^ 1);
            }
            else
            {
                rotate(t, d1 ^ 1);
                rotate(t, d2 ^ 1);
            }
        }
        else
            rotate(t, d1 ^ 1);
    }
}
void insert(int val)
{
    splay(root->size - 1);
    node *k = root->ch[1];
    root->ch[1] = new node(val);
    root->ch[1]->ch[1] = k;
    k->pull_up();
    root->ch[1]->pull_up();
    root->pull_up();
}
int get_maxnum(int len)
{
    int from = root->size - len;
    int to = from + len - 1;
    splay(to + 1, root);
    splay(from - 1, root->ch[0]);
    return root->ch[0]->ch[1]->maxnum;
}
}
int main()
{
    using namespace splay;
    cin >> m >> d;
    init();
    char a;
    int b;
    while(m--)
    {
        cin >> a >> b;
        switch(a)
        {
        case ‘A‘:
            insert((b + t) % d);
            break;
        case ‘Q‘:
            t = get_maxnum(b);
            cout << t << endl;
            break;
        }
    }
    return 0;
}

线段树解法

M<=2e5,也就是极限状况下最多2e5个数。开个长度是2e5的线段树,再记录下已经加了N个数了。每次插入就是更改第N+1个元素,查询就是查询区间[N-L+1,N]的最大值。

懒得重写一遍了……

时间: 2024-11-05 21:46:24

【JSOI2008】最大数的相关文章

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

012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MB Description 现在请求你维护一个数列,要求提供以下两种操作:1. 查询操作.语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值.限制:L不超过当前数列的长度.2. 插入操作.语法:A n 功能:将n加上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取模,将所得答案插入到数列

洛谷 P1198 [JSOI2008]最大数

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

[JSOI2008]最大数maxnumber

[JSOI2008]最大数maxnumberTime Limit: 3 Sec  Memory Limit: 162 MBSubmit: 6471  Solved: 2756[Submit][Status][Discuss] Description 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作.语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值.限制:L不超过当前数列的长度. 2. 插入操作.语法:A n 功能:将n加上t,其中t是最近一次查询操作的答案

bzoj-1012 1012: [JSOI2008]最大数maxnumber(线段树)

题目链接: 1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MB Description 现在请求你维护一个数列,要求提供以下两种操作:1. 查询操作.语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值.限制:L不超过当前数列的长度.2. 插入操作.语法:A n 功能:将n加上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取模,将所得

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

裸的线段树...因为数组开小了而一直RE..浪费了好多时间.. -------------------------------------------------------------------------- #include<cstdio> #include<algorithm> #include<cstring> #include<cctype> #include<iostream> #define rep(i,n) for(int i=

洛谷P1198 [JSOI2008]最大数

P1198 [JSOI2008]最大数 267通过 1.2K提交 题目提供者该用户不存在 标签线段树各省省选 难度提高+/省选- 提交该题 讨论 题解 记录 最新讨论 WA80的戳这QwQ BZOJ都过了,洛谷竟然过不了… 为什么过不了 = =我想说这题加优读会WA?… 谁说pascal只能80,要换c++… 线段树为什么是80? 题目描述 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作. 语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值. 限制:L不超

luogu P1198 [JSOI2008]最大数

二次联通门 :  luogu P1198 [JSOI2008]最大数 /* luogu P1198 [JSOI2008]最大数 线段树水过... 建一颗空树 然后单点插入, 区间查询即可 */ #include <cstdio> #define Max 200000 void read (long long &now) { now = 0; register char word = getchar (); while (word > '9' || word < '0') w

BZOJ 1012: [JSOI2008]最大数maxnumber 单调栈

单调栈 1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MB Submit: 4988  Solved: 2252 [Submit][Status][Discuss] Description 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作.语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值.限制:L不超过当前数列的长度. 2. 插入操作.语法:A n 功能:将n加上t,其中

1012: [JSOI2008]最大数maxnumber

1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 4435  Solved: 2000[Submit][Status] Description 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作.语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值.限制:L不超过当前数列的长度. 2. 插入操作.语法:A n 功能:将n加上t,其中t是最近一次查询操作的答案(如

[JSOI2008]最大数 --线段树

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