T2 P3293 [SCOI2016]美味
思路:
按照数位一位一位的贪心,加了一个
x
x
x,考虑对于所有的
a
i
+
x
a_i+x
ai+x 与
b
b
b 的按位异或
假设我们已经处理到
b
b
b 的第
i
i
i 位,假设是
1
1
1。
那么我们只需要查找是否存在
a
j
+
x
aj+x
aj+x 使得其二进制第
i
i
i 位数字是
0
0
0,设当前结果是
a
n
s
ans
ans,那么我们需要查找的数的大小就是在区间
[
a
n
s
−
x
,
a
n
s
+
(
1
<
<
i
)
−
1
−
x
]
[ans-x,ans+(1<<i)-1-x]
[ans−x,ans+(1<<i)−1−x],显然这个区间前
i
−
1
i-1
i−1 位都相同
两个区间限制,主席树维护
代码:
#include <bits/stdc++.h>
using namespace std;
namespace IO {
char _buf[1 << 21], *_p1 = _buf, *_p2 = _buf;
#define ch() \
(_p1 == _p2 && \
(_p2 = (_p1 = _buf) + fread(_buf, 1, 1 << 21, stdin), _p1 == _p2) \
? EOF \
: *_p1++)
inline int in() {
int s = 0, f = 1;
char x = ch();
for (; x < '0' || x > '9'; x = ch())
if (x == '-') f = -1;
for (; x >= '0' && x <= '9'; x = ch()) s = (s * 10) + (x & 15);
return f == 1 ? s : -s;
}
char buf_[1 << 21];
int p1_ = -1;
inline void flush() {
fwrite(buf_, 1, p1_ + 1, stdout);
p1_ = -1;
}
inline void pc(char x) {
if (p1_ == (1 << 21) - 1) flush();
buf_[++p1_] = x;
}
inline void out(int x) {
char k[30];
int pos = 0;
if (!x) {
pc('0');
return;
}
if (x < 0) {
pc('-');
x = -x;
}
while (x) {
k[++pos] = (x % 10) | 48;
x /= 10;
}
for (int i = pos; i; i--) pc(k[i]);
return;
}
inline void out(string x) {
int k = x.size();
for (int i = 0; i < k; i++) pc(x[i]);
}
} // namespace IO
using namespace IO;
const int A = 2e5 + 5;
const int Max = 1e5;
const int logA = 20;
int n, m;
int val[A];
struct SGT {
int ls, rs;
int num;
} tr[4 * logA * A];
int rt[A], tot;
#define ls(x) tr[x].ls
#define rs(x) tr[x].rs
inline void build(int y, int &x, int l, int r, int val) {
x = ++tot;
tr[x] = tr[y];
tr[x].num++;
if (l == r) return;
int mid = (l + r) >> 1;
if (val <= mid)
build(ls(y), ls(x), l, mid, val);
else
build(rs(y), rs(x), mid + 1, r, val);
return;
}
inline int find(int x, int y, int ql, int qr, int l, int r) {
if (tr[x].num == tr[y].num || qr < l || ql > r) return 0;
if (l >= ql && r <= qr) return tr[x].num - tr[y].num;
int mid = (l + r) >> 1;
int num = 0;
if (ql <= mid) num += find(ls(x), ls(y), ql, qr, l, mid);
if (qr >= mid + 1) num += find(rs(x), rs(y), ql, qr, mid + 1, r);
return num;
}
#undef ls
#undef rs
signed main() {
n = in(), m = in();
for (int i = 1; i <= n; i++) val[i] = in();
for (int i = 1; i <= n; i++) build(rt[i - 1], rt[i], 0, Max, val[i]);
while (m--) {
int b = in(), x = in(), l = in(), r = in();
int ans = 0;
for (int i = logA; ~i; i--) {
if (b & (1 << i) &&
!find(rt[r], rt[l - 1], ans - x, ans - x + (1 << i) - 1, 0, Max))
ans |= (1 << i);
if (!(b & (1 << i)) && find(rt[r], rt[l - 1], ans - x + (1 << i),
ans - x + (1 << (i + 1)) - 1, 0, Max))
ans |= (1 << i);
}
out(ans ^ b), pc('\n');
}
flush();
return 0;
}