题解 P5283 【[十二省联考2019]异或粽子】

HomuraCat

2019-04-25 21:53:16

Solution

可持久化$Trie$树+堆 刚开始想着在$Trie$树上二分来降一个$log$来着然后发现自己$sb$了 最开始的前缀和不用说了 然后我们可以用堆维护最大值,然后去扩展其它最大值,具体来讲,我们首先需要建一个可持久化$Trie$,滋磁区间$xor$最值查询,然后记录一个五元组$(l,r,val,ori,pos)$表示在区间$[l,r]$之间的某个数数与$ori$取异或最大为$val$且这个数的位置是$pos$,然后每次从堆里取$val$最大的然后分裂就行。 ```cpp #include<bits/stdc++.h> #define Re register #define fo(i, a, b) for (Re int i = (a); i <= (b); ++i) #define fd(i, a, b) for (Re int i = (a); i >= (b); --i) #define edge(i, u) for (Re int i = head[u], v = e[i].v; i; i = e[i].nxt, v = e[i].v) #define pb push_back #define F first #define S second #define ll long long #define inf 1000000007 #define mp std::make_pair #define eps 1e-4 #define mod 10086 #define lowbit(x) (x & -x) #define N 500005 #define ls (u << 1) #define rs (u << 1 | 1) #define cl(arr) memset(arr, 0, sizeof arr) #define bset std::bitset<N> inline void read (int &x) { x = 0; Re char ch = getchar(); while (!isdigit(ch)) ch = getchar(); while (isdigit(ch)) x = (x << 3) + (x << 1) + ch - '0', ch = getchar(); } struct trie { int rt[N], t[N * 33][2], cnt, sum[N * 33], id[N * 33]; inline void ins (int &uu, int pu, int val, int idx) { uu = ++cnt; int u = uu; sum[u] = sum[pu] + 1; fd (i, 31, 0) { bool now = (val >> i & 1); t[u][now] = ++cnt; t[u][!now] = t[pu][!now]; pu = t[pu][now]; u = t[u][now]; sum[u] = sum[pu] + 1; } id[u] = idx; } #define pi std::pair<ll, int> inline pi query (int u, int pu, int val) { pi ret = mp(0, 0); fd (i, 31, 0) { bool now = (val >> i & 1); if (sum[t[u][!now]] - sum[t[pu][!now]]) { ret.F |= 1ll << i; u = t[u][!now]; pu = t[pu][!now]; } else { u = t[u][now]; pu = t[pu][now]; } } ret.S = id[u]; return ret; } } t; unsigned int a[N]; int n, m; struct node { ll l, r, val, ori, pos; friend bool operator < (node x, node y) { return x.val < y.val; } }; std::priority_queue<node> q; int main () { scanf("%d %d", &n, &m); fo (i, 1, n) { scanf("%u", &a[i + 1]); a[i + 1] ^= a[i]; } ++n; fo (i, 1, n) t.ins(t.rt[i], t.rt[i - 1], a[i], i); fo (i, 1, n) { pi now = t.query(t.rt[i - 1], t.rt[0], a[i]); q.push((node) {1, i - 1, now.F, a[i], now.S}); } ll ans = 0; while (m--) { node u = q.top(); q.pop(); ans += u.val; if (u.l < u.pos) { pi now = t.query(t.rt[u.pos - 1], t.rt[u.l - 1], u.ori); q.push((node) {u.l, u.pos - 1, now.F, u.ori, now.S}); } if (u.pos < u.r) { pi now = t.query(t.rt[u.r], t.rt[u.pos], u.ori); q.push((node) {u.pos + 1, u.r, now.F, u.ori, now.S}); } } printf("%lld", ans); return 0; } ```