【洛谷6105】[Ynoi2010] y-fast trie(set)

点此看题面

大致题意: 给定一个集合(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;
}
原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu6105.html