题解 P6105 【[Ynoi2010]iepsmCmq】
Owen_codeisking · · 题解
比赛时 T2 忘开 long long 自闭了好长时间,这是赛后写的。
好像这题还蛮套路的?
首先我们先分类讨论(加入集合
若此题离线,那么考虑线段树分治,每次加进去的时候把这个数的最佳匹配找出来,对答案取个
现在考虑在线。若删除的话,有可能这个数是多个数的最佳匹配,那么一次删除涉及最多
那么我们换个角度考虑,只维护双向匹配的对数,这样每次修改只涉及
为什么呢?
一般这种最优化数对的题,都是先弄出个
假设
这样的数对显然最多
不过你一次修改需要找出这个数的最优匹配,最优匹配的最优匹配,最优匹配的最优匹配的最优匹配,常数比较大,细节有一点。建议画个图把细节理清楚再写。还有,
最短代码
#include <bits/stdc++.h>
using namespace std;
int n,c,sz;
multiset<int> a,b;
multiset<int>::iterator it;
inline int best(int x,int op)
{
if(x==-1) return -1;
it=a.upper_bound(c-1-x);
if(it==a.begin()) return -1;
it--;
if(op==1 && *it==x && a.count(x)==1)
return (it==a.begin())?-1:*--it;
else
return *it;
}
inline void insert(int x)
{
sz++;
if(sz==1) { a.insert(x); return; }
int y=best(x,0),z=best(y,1),w=best(z,1);
if(y!=-1 && z<x)
{
if(z!=-1 && y==w) b.erase(b.find(y+z));
b.insert(x+y);
}
a.insert(x);
}
inline void erase(int x)
{
a.erase(a.find(x)),sz--;
if(!sz) return;
int y=best(x,0),z=best(y,1),w=best(z,1);
if(y!=-1 && z<x)
{
if(z!=-1 && y==w) b.insert(y+z);
b.erase(b.find(x+y));
}
}
inline int query()
{
it=--a.end();
if(a.count(*it)>=2) return *it*2%c;
else return (*it+*--it)%c;
}
int main()
{
scanf("%d%d",&n,&c);
int op,x,lastans=0;
while(n--)
{
scanf("%d%d",&op,&x); x^=lastans;
if(op==1) insert(x%c);
else erase(x%c);
if(sz<2) puts("EE"),lastans=0;
else printf("%d\n",lastans=max(query(),b.empty()?0:*--b.end()));
}
return 0;
}
(估计我大括号不换行会更短)
题出得好!难度适中,覆盖知识点广,码量不大,解法比较自然,给出题人点赞!
就是没啥 gal 的背景,差评
upd: 好像不能每次都过?