[DS记录]P6105 [Ynoi2010] y-fast trie

command_block

2021-06-30 16:44:02

Personal

**题意** : 给定一个常数 $C$,你需要维护一个集合 $S$ ,初始时为空。 有 $n$ 次操作: - 操作1:给出 $x$,插入一个元素 $x$,保证之前集合中没有 $x$ 这个元素 - 操作2:给出 $x$,删除一个元素 $x$,保证之前集合中存在 $x$ 这个元素 每次操作结束后,需要输出从 $S$ 集合中选出两个不同的元素的和 $\bmod\ C$ 的最大值,或指出 $S$ 集合中不足两个元素。 强制在线,$n\leq 5\times 10^5,C,x\leq 2^{63}-1$ ,时限$\texttt{1s}$。 ------------ 将输入的所有 $x$ 都先模 $C$。 对于和,分 $a+b<C$ 和 $a+b\geq C$ 两类讨论。 对于 $\geq C$ 的情况,只需取 $S$ 中的最大值与次大值进行尝试。 对于 $<C$ 的情况,为每个数 $u$ 找出 $<C-u$ 的最大的 $v$ ,则 $u+v$ 是关于 $u$ 的最佳方案。记为 $u\rightarrow v$ ,称 $u$ 为左端, $v$ 为右端。 考虑动态维护这种匹配。某个左端对应的右端是唯一的,但同一个右端可能对应多个左端,无法保证复杂度。 注意到若 $u_1<u_2$ 且同时有 $u_1,u_2\rightarrow v$ ,则 $u_2\rightarrow v$ 的贡献必定大于 $u_1\rightarrow v$ 的贡献。 于是,对于每个右端,我们只需保留最大的左端。这样化简之后,每个元素相关的匹配数都是 $O(1)$ 的。 又能发现,若 $x$ 作为右端时 $y$ 是最优左端,那么 $y$ 是右端时 $x$ 也是最优左端。这种匹配关系是双向的。 我们猜想修改对这些匹配的影响是 $O(1)$ 的。 插入 $x$ 时,考虑其匹配。 先以 $x$ 作为左端找出右端 $y$ ,再查看 $y$ 原来的匹配 $z$,看看 $x$ 是否 $>z$ ,若是则替代之。 替代后 $z$ 必定无匹配。( $z$ 的右端是 $y$ ,但 $y$ 不认 $z$ ) 删除 $x$ 时,考虑其匹配。 若没有匹配则直接删除。若匹配 $y$,则将两者同时删除,再加入 $y$ 。 注意可能存在相同的数值。 复杂度 $O(n\log n)$。 ```cpp #include<algorithm> #include<cstdio> #include<queue> #include<set> #define ull unsigned long long #define Pr pair<ull,int> #define fir first #define sec second #define mp make_pair #define Itor set<Pr>::iterator #define ll long long #define MaxN 500500 using namespace std; struct Heap{ priority_queue<ull> q0,q1; void push(ull x){q1.push(x);} void del(ull x){q0.push(x);} ull top(){ while(!q0.empty()&&q0.top()==q1.top()){q0.pop();q1.pop();} return q1.empty() ? 0 : q1.top(); } }q; set<Pr> s; int m,n,tp[MaxN];ull C,w[MaxN]; void insert(int u) { Itor it=s.lower_bound(mp(C-w[u],0)); if (it!=s.begin()){ int v=(--it)->sec; if (!tp[v]){tp[v]=u;tp[u]=v;q.push(w[u]+w[v]);} else if (w[u]>w[tp[v]]){ int t=tp[v]; tp[t]=0;q.del(w[t]+w[v]); tp[v]=u;tp[u]=v;q.push(w[u]+w[v]); } }s.insert(mp(w[u],u)); } int main() { scanf("%d%llu",&m,&C); ull las=0; for (int i=1,op;i<=m;i++){ ull x; scanf("%d%llu",&op,&x); x=(x^las)%C; if (op==1){w[++n]=x;insert(n);} else { Itor it=s.lower_bound(mp(x,0)); int u=it->sec; if (!tp[u])s.erase(it); else { int v=tp[u]; tp[u]=tp[v]=0;q.del(w[u]+w[v]); s.erase(it);s.erase(mp(w[v],v)); insert(v); } } if (s.size()<=1){puts("EE");las=0;} else { Itor it=s.end(); ull ans=0; it--;ans+=it->fir; it--;ans+=it->fir; printf("%llu\n",las=max(q.top(),ans%C)); } }return 0; } ```