1. 程式人生 > >[十二省聯考2019]異或粽子 01trie

[十二省聯考2019]異或粽子 01trie

wro std 主席樹 每次 鏈接 http -i ons getchar

[十二省聯考2019]異或粽子 01trie

鏈接

luogu

思路

首先求前k大的(xo[i]^xo[j])(i<j)。
考場上只想到01trie,不怎麽會寫可持久,就寫了n個01trie,和直接sort一樣、、
咳咳,官方題解是。
一個堆維護i為終點,可以取得位置為\([L,R]\)的最大值為val。
每次選最大的,然後將這個點分裂成兩個:
i為終點,可以取得位置為\([L,x-1]\)的最大值為\(val_1\)
i為終點,可以取得位置為\([x+1,R]\)的最大值為\(val_2\)
具體咋維護,可持久01trie(他應該就是說的主席樹,忘記啦)。
其實可以直接是直接記錄當前應該取第幾大,建立可持久化01trie

還有一種是把k*2,這樣消去了大小限制,直接建立一顆01trie,在上面跑k大,最後除以2
對角線上是有重復的,但是你一定選不到呀,xor起來為0

錯誤

1.一個hello wrold居然跑10s,垃圾病毒防護天天掃我exe。
2.我居然不知道trie可以求第k大xor值,菜的一批、、、、
3.這細節,好麻煩,不知道為啥不能從0開始標號,不知道for從0開始

代碼

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 5e5 + 6;
ll read() {
    ll x = 0, f = 1; char s = getchar();
    for (; s > '9' || s < '0'; s = getchar()) if (s == '-') f = -1;
    for (; s >= '0' && s <= '9'; s = getchar()) x = x * 10 + s - '0';
    return x * f;
}
int n, k, cnt=1, num[N];
ll a[N];
struct node {
    int ch[2], siz;
} e[N * 35];
priority_queue<pair<ll, int> > q;
void insert(ll x) {
    int p = 1;
    for (int i = 31; i >= 0; --i) {
        bool T_T = x & (1LL << i);
        e[p].siz++;
        if (!e[p].ch[T_T])
            e[p].ch[T_T] = ++cnt;
        p = e[p].ch[T_T];
    }
    e[p].siz++;
}
ll k_th(ll x, int k) {
    if (k > n)
        return 0;
    ll ans = 0;
    int p = 1;
    for (int i = 31; i >= 0; --i) {
        bool T_T = x & (1LL << i);
        if (e[e[p].ch[T_T ^ 1]].siz >= k)
            ans = ans | (1LL << i), p = e[p].ch[T_T ^ 1];
        else
            k -= e[e[p].ch[T_T ^ 1]].siz, p = e[p].ch[T_T];
    }
    return ans;
}
int main() {
    n = read(), k = read() * 2;
    insert(0);
    for (int i = 1; i <= n; ++i) a[i] = a[i - 1] ^ read(), insert(a[i]);
    for (int i = 0; i <= n; ++i) q.push(make_pair(k_th(a[i],num[i]=1),i));
    ll ans = 0;
    while (k--) {
        pair<ll, int> u = q.top();
        q.pop();
        ans += u.first;
        u.first=k_th(a[u.second],++num[u.second]);
        if(num[u.second]<n) q.push(u);
    }
    cout << ans / 2 << "\n";
    return 0;
}

[十二省聯考2019]異或粽子 01trie