Luogu P6105 [Ynoi2010]y-fast trie
阿新 • • 發佈:2020-10-07
注意到我們可以給\(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\)
如果\(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; }