Luogu P6105 [Ynoi2010]y-fast trie

注意到我们可以给\(x\)\(C\)取模,这样\((i+j)\mod C\)就只有两种情况了

  • \(i+j<C\),此时\((i+j)\mod C=i+j\)
  • \(i+j\ge C\),此时\((i+j)\mod C=i+j-C\)

考虑第二种情况很简单,我们找出所有数的最大的两个数更新答案即可,考虑第一种情况怎么搞

我们定义一个数\(x\)最佳匹配为满足\(x+y<C\)的最大的\(y\)

容易发现,所有的互为最佳匹配的数对中一定包含有最后的答案,我们考虑再用一个mutiset来维护所有互为最佳匹配的数对和

因此在插入时,设操作数为\(x\),我们先找到它的最佳匹配\(y\),接着再找到\(y\)的最佳匹配\(z\)

如果\(x\ge z\)那么说明\(x\)代替\(z\)\(y\)互成最佳匹配,因此我们加入\(x+y\),并且如果\(z\)的最佳匹配也是\(y\)就删去\(y+z\)

删除的情况同理,全部用multiset维护即可,注意一些细节就可以通过这道题

#include<cstdio>
#include<set>
#include<iostream>
#define RI register int
#define CI const int&
using namespace std;
int n,m,x,opt,ans; multiset <int> all,s;
inline int CP(CI x,CI tp)
{
	if (!~x) return -1; multiset <int>:: iterator it=all.upper_bound(m-1-x);
	if (it==all.begin()) return -1; if (--it,tp&&*it==x&&all.count(x)==1)
	return it==all.begin()?-1:*(--it); else return *it;
}
inline void insert(CI x)
{
	if (all.empty()) return (void)(all.insert(x));
	int y=CP(x,0),z=CP(y,1); if (~y&&x>=z)
	{
		if (~z&&CP(z,1)==y) s.erase(s.find(y+z)); s.insert(x+y);
	}
	all.insert(x);
}
inline void remove(CI x)
{
	if (all.erase(all.find(x)),all.empty()) return;
	int y=CP(x,0),z=CP(y,1); if (~y&&x>=z)
	{
		if (~z&&CP(z,1)==y) s.insert(y+z); s.erase(s.find(x+y));
	}
}
inline int G(void)
{
	int x=*(--all.end()); all.erase(all.find(x));
	int y=*(--all.end()); all.insert(x); return (x+y)%m;
}
int main()
{
	//freopen("hl.in","r",stdin); freopen("hl.out","w",stdout);
	for (scanf("%d%d",&n,&m);n;--n)
	{
		scanf("%d%d",&opt,&x); x^=ans; if (opt==2) remove(x%m); else insert(x%m);
		if (all.size()<2) puts("EE"),ans=0;
		else printf("%d\n",ans=max(G(),s.empty()?0:*(--s.end())));
	}
	return 0;
}
posted @ 2020-10-07 11:18  空気力学の詩  阅读(119)  评论(0编辑  收藏  举报