题目大意:有$n(n\leqslant10^5)$个门,每个问有一个运算符$\oplus(\oplus\in\{OR,AND,XOR\})$和一个参数$t(t\leqslant10^9)$,求初始值在$[0,m(m\leqslant10^9)]$中时,按顺序经过这$n$个门后最大的值是多少
题解:发现$\oplus$都是位运算,也就是说,它对于每一位都是独立的,可以把$(11\dots11)_2$和$(00\dots00)_2$,丢进去跑一遍,就可以跑出每一位原来是$1$或$0$会变成什么,然后从高位到低位贪心即可。
卡点:无
C++ Code:(我先写了睡觉困难综合征,就把那道题挂成一条链,就通过了)
#include
#include
#include
namespace __IO {
int x, ch;
inline int read() {
while (!isdigit(ch = getchar())) ;
for (x = ch & 15; isdigit(ch = getchar()); ) x = x * 10 + (ch & 15);
return x;
}
unsigned long long X;
inline unsigned long long readllu() {
while (!isdigit(ch = getchar())) ;
for (X = ch & 15; isdigit(ch = getchar()); ) X = X * 10 + (ch & 15);
return X;
}
inline char readc() {
while (!isalpha(ch = getchar())) ;
return ch;
}
}
using __IO::read;
using __IO::readllu;
using __IO::readc;
const int maxn = 1000010;
const unsigned long long inf = ~0;
int Opt[maxn], __Opt[maxn];
unsigned long long Num[maxn], __Num[maxn];
int n, m, __p;
inline void calc(unsigned long long &x, int y, unsigned long long z) {
switch (y) {
case 1: x &= z; break;
case 2: x |= z; break;
case 3: x ^= z;
}
}
struct node {
unsigned long long __0, __1;
inline friend node operator + (const node &lhs, const node &rhs) {
return (node) {
(lhs.__0 & rhs.__1) | (~lhs.__0 & rhs.__0),
(lhs.__1 & rhs.__1) | (~lhs.__1 & rhs.__0)
};
}
} ;
namespace SgT {
const int N = maxn << 2;
node lr[N], rl[N];
void build(const int rt, const int l, const int r) {
if (l == r) {
calc(lr[rt].__0 = 0, Opt[l], Num[l]);
calc(lr[rt].__1 = inf, Opt[l], Num[l]);
calc(rl[rt].__0 = 0, Opt[l], Num[l]);
calc(rl[rt].__1 = inf, Opt[l], Num[l]);
return ;
}
const int mid = l + r >> 1, lc = rt << 1, rc = rt << 1 | 1;
build(lc, l, mid), build(rc, mid + 1, r);
lr[rt] = lr[lc] + lr[rc];
rl[rt] = rl[rc] + rl[lc];
}
int pos;
void __modify(const int rt, const int l, const int r) {
if (l == r) {
calc(lr[rt].__0 = 0, Opt[l], Num[l]);
calc(lr[rt].__1 = inf, Opt[l], Num[l]);
calc(rl[rt].__0 = 0, Opt[l], Num[l]);
calc(rl[rt].__1 = inf, Opt[l], Num[l]);
return ;
}
const int mid = l + r >> 1, lc = rt << 1, rc = rt << 1 | 1;
if (pos <= mid) __modify(lc, l, mid);
else __modify(rc, mid + 1, r);
lr[rt] = lr[lc] + lr[rc];
rl[rt] = rl[rc] + rl[lc];
}
void modify(int __pos, int y, unsigned long long z) {
pos = __pos;
Opt[pos] = y;
Num[pos] = z;
__modify(1, 1, n);
}
int L, R;
node res;
void querylr(const int rt, const int l, const int r) {
if (L <= l && R >= r) {
res = res + lr[rt];
return ;
}
const int mid = l + r >> 1;
if (L <= mid) querylr(rt << 1, l, mid);
if (R > mid) querylr(rt << 1 | 1, mid + 1, r);
}
void queryrl(const int rt, const int l, const int r) {
if (L <= l && R >= r) {
res = res + rl[rt];
return ;
}
const int mid = l + r >> 1;
if (R > mid) queryrl(rt << 1 | 1, mid + 1, r);
if (L <= mid) queryrl(rt << 1, l, mid);
}
node query(int __L, int __R) {
res.__0 = 0, res.__1 = inf;
if (__L <= __R) {
L = __L, R = __R;
querylr(1, 1, n);
} else {
L = __R, R = __L;
queryrl(1, 1, n);
}
return res;
}
}
int head[maxn], cnt;
struct Edge {
int to, nxt;
} e[maxn << 1];
inline void addedge(int a, int b) {
e[++cnt] = (Edge) { b, head[a] }; head[a] = cnt;
e[++cnt] = (Edge) { a, head[b] }; head[b] = cnt;
}
int fa[maxn], dep[maxn], sz[maxn];
int dfn[maxn], idx, top[maxn], son[maxn];
void dfs1(int u) {
sz[u] = 1;
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
if (v != fa[u]) {
fa[v] = u;
dep[v] = dep[u] + 1;
dfs1(v);
if (!son[u] || sz[v] > sz[son[u]]) son[u] = v;
sz[u] += sz[v];
}
}
}
void dfs2(int u) {
dfn[u] = ++idx;
int v = son[u];
if (v) top[v] = top[u], dfs2(v);
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
if (v != fa[u] && v != son[u]) {
top[v] = v;
dfs2(v);
}
}
}
unsigned long long query(int x, int y, unsigned long long z) {
static node res, S[maxn];
int tot = 0;
res.__0 = 0, res.__1 = inf;
while (top[x] != top[y]) {
if (dep[top[x]] > dep[top[y]]) {
res = res + SgT::query(dfn[x], dfn[top[x]]);
x = fa[top[x]];
} else {
S[++tot] = SgT::query(dfn[top[y]], dfn[y]);
y = fa[top[y]];
}
}
res = res + SgT::query(dfn[x], dfn[y]);
while (tot) res = res + S[tot--];
unsigned long long ans = 0, ret = 0;
for (int i = 63; ~i; --i) {
if (res.__0 >> i & 1) ret |= 1ull << i;
else if (res.__1 >> i & 1) {
if ((ans | 1ull << i) <= z) {
ans |= 1ull << i;
ret |= 1ull << i;
}
}
}
return ret;
}
unsigned long long __z;
int main() {
n = read(), __z = readllu();
for (int i = 1; i <= n; ++i) {
__Opt[i] = readc(), __Num[i] = readllu();
switch (__Opt[i]) {
case 'A': __Opt[i] = 1; break;
case 'O': __Opt[i] = 2; break;
case 'X': __Opt[i] = 3;
}
}
for (int i = 1, a, b; i < n; ++i) {
a = i, b = i + 1;
addedge(a, b);
}
dfs1(1), dfs2(top[1] = 1);
for (int i = 1; i <= n; ++i) Opt[dfn[i]] = __Opt[i], Num[dfn[i]] = __Num[i];
SgT::build(1, 1, n);
m = 1;
while (m --> 0) {
static int op, x, y;
static unsigned long long z;
op = 1, x = 1, y = n, z = __z;
if (op == 1) {
printf("%llu\n", query(x, y, z));
} else {
SgT::modify(dfn[x], y, z);
}
}
return 0;
}