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;
}
posted @ 2021-09-02 21:06  lahlah  阅读(29)  评论(0编辑  收藏  举报