[十二省联考2019]异或粽子

很裸的一道可持久化trie,只需要按照主席树的套路,每次求区间第k大的异或值,套路和NOI2010超级钢琴一样,不过打错下标wa了半天还是非常的真实。

另外,这个题不需要维护三元组,你只需要把优先队列开成存pair<ll, int>的就行了,ll放异或值,int放当前这个值属于哪个右端点,然后开一个rk数组存这个右端点已经取到rank几就行了,还算是送温暖。

//author Eterna
#define Hello the_cruel_world!
#pragma GCC optimize(2)
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<utility>
#include<cmath>
#include<climits>
#include<deque>
#include<functional>
#include<complex>
#include<numeric>
#include<unordered_map>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define Pi acos(-1.0)
#define ABS(x) ((x) >= 0 ? (x) : (-(x)))
#define pb(x) push_back(x)
#define lowbit(x) (x & -x)
#define FRIN freopen("C:\\Users\\Administrator.MACHENI-KA32LTP\\Desktop\\in.txt", "r", stdin)
#define FROUT freopen("C:\\Users\\Administrator.MACHENI-KA32LTP\\Desktop\\out.txt", "w", stdout)
#define FAST ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define outd(x) printf("%d\n", x)
#define outld(x) printf("%lld\n", x)
#define il inline
#define ls(x) arr[x].child[0]
#define rs(x) arr[x].child[1]
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, int> pli;
const int maxn = 5e5;
const int INF = 0x7fffffff;
const int mod = 1e9 + 7;
const double eps = 1e-7;
inline int read_int() {
    char c;
    int ret = 0, sgn = 1;
    do { c = getchar(); } while ((c < '0' || c > '9') && c != '-');
    if (c == '-') sgn = -1; else ret = c - '0';
    while ((c = getchar()) >= '0' && c <= '9') ret = ret * 10 + (c - '0');
    return sgn * ret;
}
inline ll read_ll() {
    char c;
    ll ret = 0, sgn = 1;
    do { c = getchar(); } while ((c < '0' || c > '9') && c != '-');
    if (c == '-') sgn = -1; else ret = c - '0';
    while ((c = getchar()) >= '0' && c <= '9') ret = ret * 10 + (c - '0');
    return sgn * ret;
}
struct node {
    int child[2], cnt;
}arr[45 * maxn + 5];
int tot, root[maxn + 5], n, k, pos[maxn + 5];
ll coe[40], a[maxn + 5], res;
priority_queue<pli> q;
void Insert(int& now, int pre, ll v, int cnt = 32) {
    if (!now)now = ++tot;
    arr[now].cnt = arr[pre].cnt + 1;
    if (cnt < 0)return;
    int p = (v >> cnt) & 1ll;
    arr[now].child[p ^ 1] = arr[pre].child[p ^ 1];
    Insert(arr[now].child[p], arr[pre].child[p], v, cnt - 1);
}
ll Query(int l, int r, int k, ll v, int cnt = 32) {
    if (cnt < 0)return 0;
    int p = (v >> cnt) & 1ll;
    int sum = arr[arr[r].child[p ^ 1]].cnt - arr[arr[l].child[p ^ 1]].cnt;
    if (sum >= k)return coe[cnt] + Query(arr[l].child[p ^ 1], arr[r].child[p ^ 1], k, v, cnt - 1);
    else return Query(arr[l].child[p], arr[r].child[p], k - sum, v, cnt - 1);
}
int main()
{
    coe[0] = 1;
    for (int i = 1; i <= 35; ++i)coe[i] = 2ll * coe[i - 1];
    n = read_int(), k = read_int();
    for (int i = 1; i <= n; ++i) {
        a[i] = read_ll();
        a[i] ^= a[i - 1];
        Insert(root[i], root[i - 1], a[i - 1]);
    }
    for (int i = 1; i <= n; ++i) {
        ll now = Query(root[0], root[i], 1, a[i]);
        q.push(pli(now, i));
        pos[i] = 1;
    }
    for (int i = 1; i <= k; ++i) {
        pli now = q.top();
        q.pop();
        res += now.first;
        if (pos[now.second] <= now.second) {
            ++pos[now.second];
            ll u = Query(root[0], root[now.second], pos[now.second], a[now.second]);
            q.push(pli(u, now.second));
        }
    }
    outld(res);
    //system("pause");
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/Eterna-King/p/10667804.html