洛谷 P6105 [Ynoi2010] y-fast trie
阿新 • • 發佈:2021-01-10
給定一個常數 \(C\),你需要維護一個集合 \(S\),支援 \(n\) 次操作:
- 操作1:給出 \(x\),插入一個元素 \(x\),保證之前集合中沒有 \(x\) 這個元素
- 操作2:給出 \(x\),刪除一個元素 \(x\),保證之前集合中存在 \(x\) 這個元素
每次操作結束後,需要輸出 \(\max\limits_{\substack{ i, j \in S \\ i \ne j }} \bigl( (i+j) \bmod C \bigr)\),即從 \(S\) 集合中選出兩個不同的元素,其的和 \(\bmod~C\) 的最大值,如果 \(S\) 集合中不足兩個元素,則輸出 EE
本題強制線上,每次的 \(x\) 需要 \(\operatorname{xor}\) 上上次答案 ,如果之前沒有詢問或者輸出了 EE
,則上次答案為 \(0\)。
被stl送走了= =
首先肯定要把 \(x\) 對 \(C\) 取模,然後這樣集合裡最大的兩個數的和的範圍就變成了 \([0,2C)\) ,然後討論一下最大值的情況。
如果 \(C \le i+j < 2C\) ,那就肯定是選最大值和次大值了。
如果 \(0\le i+j < C\) ,那就需要對每個數 \(i\) 找出最大的一個和他相加 \(<C\) 的數 \(j\) ,這裡我們簡稱 \(j\) 為 \(i\) 的匹配。
但是如果每次加入一個數都更新匹配複雜度顯然是不對的,所以我們考慮優化。
假如加入一個數 \(a\) ,他的匹配是 \(b\) ,然後我們找到 \(b\) 的雙向匹配 \(c\)( \(b\) 是 \(c\) 的匹配,\(c\) 也是 \(b\) 的匹配),若 \(a>c\) ,那麼顯然 \(b+c\) 是沒有用的,就可以直接扔掉,這樣子的匹配就只有 \(O(n)\)個了。
用multiset可以輕鬆解決這個問題。
Code
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <set> #include <map> using namespace std; multiset <int> a; multiset <int> b; map <int,int> mp; multiset <int>::iterator it; multiset <int>::iterator itt; int n,C,ans,sm; inline int find(int x) { it = a.lower_bound(C - x); if (it == a.begin()) return -1; return *(--it); } inline int match(int x) { if (x == -1) return -1; it = a.lower_bound(C - x); if (it == a.begin()) return -1; it--; if (*it == x) { if (it == a.begin()) return -1; return *(--it); } return *it; } inline void ins(int x) { int y = find(x),z = match(y),xx = match(z); if (y != -1 && x > z) { if (xx == y && z != -1) b.erase(b.find(z + y)); b.insert(x + y); } sm++; a.insert(x); } inline void del(int x) { sm--; a.erase(a.find(x)); int y = find(x),z = match(y),xx = match(z); if (y != -1 && x > z) { if (xx == y && z != -1) b.insert(z + y); b.erase(b.find(x + y)); } } inline int read() { int X(0),w(0);char ch(0); while (!isdigit(ch)) w |= ch == '-',ch = getchar(); while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48),ch = getchar(); return w ? -X : X; } inline int query() { int ans = 0; it = a.end(); it--; ans = *it; ans %= C; it--; ans += *it; ans %= C; itt = b.end(); if (itt != b.begin()) { itt--; ans = max(ans,*itt); } return ans; } int main() { //freopen("data.in","r",stdin); //freopen("a1.out","w",stdout); n = read();C = read(); int opt,x; while (n--) { opt = read();x = read(); x ^= ans; //cout<<opt<<"QAQ"<<x<<endl; x %= C; if (opt == 1) ins(x); else del(x); if (sm < 2) { ans = 0; printf("EE\n"); } else { ans = query(); printf("%d\n",ans); } } return 0; }