【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]的最大值。

懒得重写一遍了……

posted @ 2017-09-28 13:20  ssttkkl  阅读(188)  评论(0编辑  收藏  举报