大致题意: 给定一个集合(S),支持两种操作:加入一个数、删除一个数。每次操作后输出(max_{iin S,jin S,i ot=j}((i+j)\%C))。(强制在线)
分类
首先,第一步显然是对于读入的每个(x)将它向(C)取模,保证(0le x<C)。
要注意一点,原题中保证没有重复元素,但在我们这么一处理之后就可能会重复,我一开始就因为这个原因挂了。
既然已经满足(0le x<C)了,则((i+j)\%C)无非有两种可能:
- ((i+j)\%C=i+j-C):显然求出当前的最大值和次大值作为(i,j)即可。
- ((i+j)\%C=i+j),这个比较麻烦,是我们接下来着重讨论的。
最优匹配
我们定义(i)的最优匹配为(max_{jin S,i+j<C}j)。
不难发现,必然存在至少一对数满足它们互为最优匹配,且最优解必然是某一对互为最优匹配的数。
对于每一对互为最优匹配的(i,j),我们可以把(i+j)扔入一个(set)中存储。(注意,这里的(set)指(multiset),为了叙述方便,简称为(set))
加入一个数(x),我们需要找到它的最优匹配(y),接着找到(y)原先的最优匹配(z)。
如果(xle z),那么(y)的最优匹配显然还是(z),不予操作。
否则,如果(z)的最优匹配是(y),那么我们需要在(set)中删去(y+z)。
然后,由于(x,y)互为最优匹配,我们再把(x+y)扔入(set)中。
删除一个数(x),也是类似地找出最优匹配(y)和删去(x)后(y)的最优匹配(z)。
如果(xle z),说明(y)的最优匹配原本就是(z),删除(x)没有任何影响,不予操作。
否则,如果(z)的最优匹配时(y),那么我们需要在(set)中加入(y+z)。
然后,由于(x,y)原本互为最优匹配,删去(x)之后这对最优匹配就不存在了,因此在(set)中删去。
还有一个遗留问题,如何找到一个数的最优匹配?
我们只要另开一个(multiset),存下所有的元素,然后只要求最大的小于等于(C-x-1)就可以了。
代码
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 500000
using namespace std;
int tot,X;multiset<int> V,S;multiset<int>::iterator it;
class FastIO
{
private:
#define FS 100000
#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
#define pc(c) (C==E&&(clear(),0),*C++=c)
#define D isdigit(c=tc())
int T;char c,*A,*B,*C,*E,FI[FS],FO[FS],S[FS];
public:
I FastIO() {A=B=FI,C=FO,E=FO+FS;}
Tp I void read(Ty& x) {x=0;W(!D);W(x=(x<<3)+(x<<1)+(c&15),D);}
Tp I void writeln(Ty x) {W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);pc('
');}
I void IEE() {pc('E'),pc('E'),pc('
');}
I void clear() {fwrite(FO,1,C-FO,stdout),C=FO;}
}F;
I int Match(CI x,bool f)//求最优匹配,f表示是否要除去x自身
{
if(!~x) return -1;if((it=V.upper_bound(X-x-1))==V.begin()) return -1;//找不到返回-1
if(--it,f&&*it==x&&V.count(x)==1) return it==V.begin()?-1:*--it;return *it;//特判等于自身的情况
}
I void Ins(CI x)//插入
{
RI y,z;if(tot==1) goto End;y=Match(x,0),z=Match(y,1);
~y&&x>=z&&(~z&&y==Match(z,1)&&(S.erase(S.find(y+z)),0),S.insert(x+y),0);End:V.insert(x);
}
I void Del(CI x)//删除
{
if(V.erase(V.find(x)),!tot) return;RI y=Match(x,0),z=Match(y,1);
~y&&x>=z&&(~z&&y==Match(z,1)&&(S.insert(y+z),0),S.erase(S.find(x+y)),0);
}
I int QV() {return V.count(*(it=--V.end()))>1?(*it<<1)%X:(*it+*--it)%X;}//(i+j)%C=i+j-C
I int QS() {return S.empty()?-1:*--S.end();}//(i+j)%C=i+j
int main()
{
RI Qt,op,x,lst=0;F.read(Qt),F.read(X);W(Qt--)
F.read(op),F.read(x),x^=lst,op==1?(++tot,Ins(x%X)):(--tot,Del(x%X)),//tot记录元素个数
tot<2?(lst=0,F.IEE()):F.writeln(lst=max(QV(),QS()));//tot<2输出EE,否则询问
return F.clear(),0;
}