给定一个常数 (C),你需要维护一个集合 (S),支持 (n) 次操作:
- 操作1:给出 (x),插入一个元素 (x),保证之前集合中没有 (x) 这个元素
- 操作2:给出 (x),删除一个元素 (x),保证之前集合中存在 (x) 这个元素
每次操作结束后,需要输出 (maxlimits_{substack{ i, j in S \ i
e j }} igl( (i+j) mod C igr)),即从 (S) 集合中选出两个不同的元素,其的和 (mod~C) 的最大值,如果 (S) 集合中不足两个元素,则输出 EE
。
本题强制在线,每次的 (x) 需要 (operatorname{xor}) 上上次答案 ,如果之前没有询问或者输出了 EE
,则上次答案为 (0)。
(1leq n leq 5 imes 10^5),(1leq Cleq 1073741823),(0leq xleq 1073741823)。
被stl送走了= =
首先肯定要把 (x) 对 (C) 取模,然后这样集合里最大的两个数的和的范围就变成了 ([0,2C)) ,然后讨论一下最大值的情况。
如果 (C le i+j < 2C) ,那就肯定是选最大值和次大值了。
如果 (0le 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
");
}
else
{
ans = query();
printf("%d
",ans);
}
}
return 0;
}