洛谷 P6105 [Ynoi2010] y-fast trie

给定一个常数 \(C\),你需要维护一个集合 \(S\),支持 \(n\) 次操作:

  • 操作1:给出 \(x\),插入一个元素 \(x\),保证之前集合中没有 \(x\) 这个元素
  • 操作2:给出 \(x\),删除一个元素 \(x\),保证之前集合中存在 \(x\) 这个元素

每次操作结束后,需要输出 \(\max\limits_{\substack{ i, j \in S \\ i \ne j }} \bigl( (i+j) \bmod C \bigr)\),即从 \(S\) 集合中选出两个不同的元素,其的和 \(\bmod~C\) 的最大值,如果 \(S\) 集合中不足两个元素,则输出 EE

本题强制在线,每次的 \(x\) 需要 \(\operatorname{xor}\) 上上次答案 ,如果之前没有询问或者输出了 EE,则上次答案为 \(0\)

\(1\leq n \leq 5\times 10^5\)\(1\leq C\leq 1073741823\)\(0\leq x\leq 1073741823\)


被stl送走了= =

首先肯定要把 \(x\)\(C\) 取模,然后这样集合里最大的两个数的和的范围就变成了 \([0,2C)\) ,然后讨论一下最大值的情况。

如果 \(C \le i+j < 2C\) ,那就肯定是选最大值和次大值了。

如果 \(0\le i+j < C\) ,那就需要对每个数 \(i\) 找出最大的一个和他相加 \(<C\) 的数 \(j\) ,这里我们简称 \(j\)\(i\) 的匹配。

但是如果每次加入一个数都更新匹配复杂度显然是不对的,所以我们考虑优化。

假如加入一个数 \(a\) ,他的匹配是 \(b\) ,然后我们找到 \(b\) 的双向匹配 \(c\)\(b\)\(c\) 的匹配,\(c\) 也是 \(b\) 的匹配),若 \(a>c\) ,那么显然 \(b+c\) 是没有用的,就可以直接扔掉,这样子的匹配就只有 \(O(n)\)个了。

用multiset可以轻松解决这个问题。

Code

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <set>
#include <map>
using namespace std;
multiset <int> a;
multiset <int> b;
map <int,int> mp;
multiset <int>::iterator it;
multiset <int>::iterator itt;
int n,C,ans,sm;
inline int find(int x)
{
    it = a.lower_bound(C - x);
    if (it == a.begin())
        return -1;
    return *(--it);
}
inline int match(int x)
{
    if (x == -1)
        return -1;
    it = a.lower_bound(C - x);
    if (it == a.begin())
        return -1;
    it--;
    if (*it == x)
    {
        if (it == a.begin())
            return -1;
        return *(--it);
    }
    return *it;
}
inline void ins(int x)
{
    int y = find(x),z = match(y),xx = match(z);
    if (y != -1 && x > z)
    {
        if (xx == y && z != -1)
            b.erase(b.find(z + y));
        b.insert(x + y);
    }    
    sm++;
    a.insert(x);
}
inline void del(int x)
{
    sm--;
    a.erase(a.find(x));
    int y = find(x),z = match(y),xx = match(z);
    if (y != -1 && x > z)
    {
        if (xx == y && z != -1)
            b.insert(z + y);
        b.erase(b.find(x + y));
    }
}
inline int read()
{
    int X(0),w(0);char ch(0);
    while (!isdigit(ch)) w |= ch == '-',ch = getchar();
    while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48),ch = getchar();
    return w ? -X : X;
}
inline int query()
{
    int ans = 0;
    it = a.end();
    it--;
    ans = *it;
    ans %= C;
    it--;
    ans += *it;
    ans %= C;
    itt = b.end();
    if (itt != b.begin())
    {
        itt--;
        ans = max(ans,*itt);
    }
    return ans;
}
int main()
{
    //freopen("data.in","r",stdin);
    //freopen("a1.out","w",stdout);
    n = read();C = read();
    int opt,x;
    while (n--)
    {
        opt = read();x = read();
        x ^= ans;
        //cout<<opt<<"QAQ"<<x<<endl;
        x %= C;
        if (opt == 1)
            ins(x);
        else
            del(x);
        if (sm < 2)
        {
            ans = 0;
            printf("EE\n");
        }
        else
        {
            ans = query();
            printf("%d\n",ans);
        }
    }
    return 0;
}
posted @ 2021-01-09 20:29  eee_hoho  阅读(154)  评论(0编辑  收藏  举报