[洛谷P2114][NOI2014]起床困难综合症
题目大意:有$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 <algorithm> #include <cstdio> #include <cctype> 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; }