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

求最大第$k$个异或区间和。

维护每个右端点,$r-[0,l-1]$,放入堆中维护,取出来后分裂成两个$r-[0,p),(p,l-1]$继续放入堆中维护即可

  • $2^{32}$>int
  • 可以选择二分查找最大值所位置,也可以可持续字典树的结点上返回位置。
代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121


#include <bits/stdc++.h>
using namespace std;
typedef unsigned int ll;

#define mk make_pair
const int N = 1e6 + 10;
const int mod = 1e9 + 7;

ll read()
{
ll x = 0, f = 1;
char c = getchar();
while (c < '0' || c > '9')
{
if (c == '-')
f = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
x = (x << 1) + (x << 3) + c - '0', c = getchar();
return x * f;
}
int rt[N];
struct Tri
{
int scnt, ch[N * 33][2], cnt[N * 33];
int q[N * 32];
void insert(int &pos, int pre, ll x, int id)
{
pos = ++scnt;
int tmp = pos;
cnt[tmp] = cnt[pre] + 1;
for (int i = 32; i >= 0; i--)
{
int c = (x & (1 << i)) >> i;

ch[tmp][1] = ch[pre][1];
ch[tmp][0] = ch[pre][0];
ch[tmp][c] = ++scnt;

tmp = ch[tmp][c], pre = ch[pre][c];
cnt[tmp] = cnt[pre] + 1;
}
q[tmp] = id;
}
int query(ll x, int l, int r)
{

l = (l == 0) ? 0 : rt[l - 1];
r = rt[r];
for (int i = 32; i >= 0; i--)
{
int c = (x & (1 << i)) >> i;
if ((cnt[ch[r][c ^ 1]] - cnt[ch[l][c ^ 1]]) > 0)
{
r = ch[r][c ^ 1];
l = ch[l][c ^ 1];
}
else
{
r = ch[r][c];
l = ch[l][c];
}
}
return q[r];
}
} T;

ll a[N], s[N];

struct node
{
int l, r;
ll v, maxx;
int mid;
friend bool operator<(node A, node B)
{
return A.maxx < B.maxx;
}
};

int main()
{
int n = read(), k = read();
for (int i = 1; i <= n; i++)
a[i] = read();
for (int i = 1; i <= n; i++)
s[i] = s[i - 1] ^ a[i];
int cnt = 0;
for (int i = 0; i < n; i++)
{
T.insert(rt[i], i == 0 ? 0 : rt[i - 1], s[i], i);
}
priority_queue<node> q;
for (int i = 1; i <= n; i++)
{
int id = T.query(s[i], 0, i - 1);
q.push((node){0, i - 1, s[i], s[i] ^ s[id], id});
}
ll ans = 0;
for (int i = 1; i <= k; i++)
{
node now = q.top();
q.pop();
ans += now.maxx;
int mid = now.mid;
if (mid - 1 >= now.l)
{
int id = T.query(now.v, now.l, mid - 1);
q.push((node){now.l, mid - 1, now.v, now.v ^ s[id], id});
}
if (now.r >= mid + 1)
{
int id = T.query(now.v, mid + 1, now.r);
q.push((node){mid + 1, now.r, now.v, now.v ^ s[id], id});
}
}
printf("%lld\n", ans);
}