luogu P6105 [Ynoi2010] y-fast trie
https://www.luogu.com.cn/problem/P6105
分两类讨论
- x + y > C x+y > C x+y>C,只需要取最大值和次大值即可
-
x
+
y
<
C
x+y < C
x+y<C, 每个
x
x
x一定会有一个最佳的
y
y
y使得答案最大
可以发现如果 x x x最优的是 y y y, y y y最优的是 x x x,如果存在一个 z z z最优的也是 y y y,那么 z z z是没有必要保存下来的,只用保留 x + y x+y x+y即可
删除就把 x , y x,y x,y删除,然后再把 y y y从新插入即可
具体实现可以用一个可删堆维护
a
[
x
]
+
a
[
y
]
a[x]+a[y]
a[x]+a[y]
然后用一个set维护一个
(
a
[
x
]
,
x
)
(a[x],x)
(a[x],x)表示位置和值(因为可能会有重复的,而且可以方便维护最优匹配)
可以参考代码
code:
#include<bits/stdc++.h>
#define pi pair<int, int>
#define mkp make_pair
#define ITT set<pi>::iterator
#define N 500050
using namespace std;
struct HP {
priority_queue<int> q, p;
void push(int x) { q.push(x); }
void del(int x) { p.push(x); }
int top() {
while(p.size() && p.top() == q.top()) q.pop(), p.pop();
return q.size()? q.top() : 0;
}
} q;
set<pi> S;
int n, m, mp[N], a[N], C;
void insert(int x) {
ITT it = S.lower_bound(mkp(C - a[x], 0));
if(it != S.begin()) {
-- it;
int y = (*it).second, z = mp[y];
// printf(" & %d %d %d\n", x, y, a[x] + a[y]);
if(!z) mp[x] = y, mp[y] = x, q.push(a[x] + a[y]);
else if(a[x] > a[z]) {
mp[z] = 0; mp[x] = y, mp[y] = x;
q.del(a[y] + a[z]), q.push(a[x] + a[y]);
}
}
S.insert(mkp(a[x], x));
}
int main() {
scanf("%d%d", &m, &C);
int lst = 0;
while(m --) {
int o, x;
scanf("%d%d", &o, &x);
x ^= lst; x %= C; lst = 0;
if(o == 1) a[++ n] = x, insert(n);
else {
ITT it = S.lower_bound(mkp(x, 0));
int x = (*it).second, y = mp[x];
if(!y) S.erase(it);
else {
mp[x] = mp[y] = 0;
q.del(a[x] + a[y]);
S.erase(mkp(a[x], x)), S.erase(mkp(a[y], y));
insert(y);
}
}
// for(ITT it = S.begin(); it != S.end(); it ++) printf(" %d ", (*it).first); printf(" **%d\n", x);
if(S.size() <= 1) printf("EE\n");
else {
ITT it = S.end(); it --;
lst += (*it).first; it --;
lst += (*it).first; //printf(">%d %d ", lst, q.top());
printf("%d\n", lst = max(lst % C, q.top()));
}
}
return 0;
}