转换一下变成询问区间选两个数异或的最大值, 要注意的是一个数作为左端点要-1, 所以在回滚莫队的时候用两棵字典树维护。
这个题居然n ^ 2 也能过。。。 其实用分治 + 可持久化字典树可以做到n * log(n) * log(n), 懒得写了。。。
#include<bits/stdc++.h> #define LL long long #define LD long double #define ull unsigned long long #define fi first #define se second #define mk make_pair #define PLL pair<LL, LL> #define PLI pair<LL, int> #define PII pair<int, int> #define SZ(x) ((int)x.size()) #define ALL(x) (x).begin(), (x).end() #define fio ios::sync_with_stdio(false); cin.tie(0); using namespace std; const int N = 5e4 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 998244353; const double eps = 1e-8; const double PI = acos(-1); template<class T, class S> inline void add(T& a, S b) {a += b; if(a >= mod) a -= mod;} template<class T, class S> inline void sub(T& a, S b) {a -= b; if(a < 0) a += mod;} template<class T, class S> inline bool chkmax(T& a, S b) {return a < b ? a = b, true : false;} template<class T, class S> inline bool chkmin(T& a, S b) {return a > b ? a = b, true : false;} const int LOG = 20; const int B = 500; int n, m, maxb, ans[N], a[N], b[N], c[N]; int BL[1007], BR[1007], belong[N]; int st[N], tot; struct Trie { int stk[N * 20], top; int ch[N * 20][2], cnt[N * 20]; int mx[N * 20], mn[N * 20]; int Rt; inline int newNode() { int x = stk[top--]; cnt[x] = ch[x][0] = ch[x][1] = 0; mx[x] = -inf; mn[x] = inf; return x; } void init() { top = 0; mx[0] = -inf; mn[0] = inf; for(int i = 1; i < N * 20; i++) stk[++top] = i; Rt = newNode(); } void del(int x) { int u = Rt; tot = 0; cnt[u]--; for(int i = LOG - 1; i >= 0; i--) { int to = ch[u][x >> i & 1]; if(i != LOG - 1 && !cnt[u]) stk[++top] = u; else st[++tot] = u; cnt[to]--; if(!cnt[to]) ch[u][x >> i & 1] = 0; u = to; } if(!cnt[u]) stk[++top] = u; else st[++tot] = u; for(int i = tot; i >= 1; i--) { int u = st[i]; mx[u] = max(mx[ch[u][0]], mx[ch[u][1]]); mn[u] = min(mn[ch[u][0]], mn[ch[u][1]]); } } void ins(int x) { int u = Rt; cnt[u]++; chkmax(mx[u], x); chkmin(mn[u], x); for(int i = LOG - 1; i >= 0; i--) { if(!ch[u][x >> i & 1]) ch[u][x >> i & 1] = newNode(); int to = ch[u][x >> i & 1]; cnt[to]++; chkmax(mx[to], x); chkmin(mn[to], x); u = to; } } int Bquery(int x) { int u = Rt; int ans = 0; bool limit = true; if(!cnt[u]) return 0; for(int i = LOG - 1; i >= 0; i--) { if(limit) { if(x >> i & 1) { if(mx[ch[u][1]] < x) return 0; u = ch[u][1]; } else { if(mx[ch[u][1]] >= x) { ans += 1 << i; u = ch[u][1]; limit = false; } else { if(mx[ch[u][0]] < x) return 0; u = ch[u][0]; } } } else { if(x >> i & 1) { if(ch[u][0]) ans += 1 << i, u = ch[u][0]; else u = ch[u][1]; } else { if(ch[u][1]) ans += 1 << i, u = ch[u][1]; else u = ch[u][0]; } } } return ans; } int Squery(int x) { int u = Rt; int ans = 0; bool limit = true; if(!cnt[u]) return 0; for(int i = LOG - 1; i >= 0; i--) { if(limit) { if(x >> i & 1) { if(mn[ch[u][0]] <= x) { ans += 1 << i; u = ch[u][0]; limit = false; } else { if(mn[ch[u][1]] > x) return 0; u = ch[u][1]; } } else { if(mn[ch[u][0]] > x) return 0; u = ch[u][0]; } } else { if(x >> i & 1) { if(ch[u][0]) ans += 1 << i, u = ch[u][0]; else u = ch[u][1]; } else { if(ch[u][1]) ans += 1 << i, u = ch[u][1]; else u = ch[u][0]; } } } return ans; } } trie[2]; struct Qus { int l, r, id; bool operator < (const Qus &rhs) const { return r < rhs.r; } }; vector<Qus> qus[1007]; int getVal(int x) { if(x & 1) return (x + 1 >> 1) & 1; else return x ^ ((x + 1 >> 1) & 1); } int main() { memset(BL, 0x3f, sizeof(BL)); memset(BR, 0xc0, sizeof(BR)); scanf("%d%d", &n, &m); for(int i = 1; i <= n; i++) { belong[i] = i / B; chkmin(BL[i / B], i); chkmax(BR[i / B], i); } for(int i = 1; i <= n; i++) { scanf("%d", &c[i]); a[i] = getVal(c[i] - 1); b[i] = getVal(c[i]); } for(int i = 1; i <= m; i++) { int l, r; scanf("%d%d", &l, &r); qus[l / B].push_back(Qus{l, r, i}); chkmax(maxb, l / B); } for(int i = 0; i <= maxb; i++) sort(ALL(qus[i])); trie[0].init(); trie[1].init(); for(int o = 0; o <= maxb; o++) { if(!SZ(qus[o])) continue; int pt = BR[o] + 1; int maxVal = 0; for(auto &q : qus[o]) { int L = q.l, R = q.r, id = q.id; int maxTmp = 0; if(R <= BR[o]) { for(int i = L; i <= R; i++) { chkmax(maxTmp, c[i]); chkmax(maxTmp, trie[0].Squery(b[i])); chkmax(maxTmp, trie[1].Bquery(a[i])); trie[0].ins(a[i]); trie[1].ins(b[i]); } for(int i = L; i <= R; i++) { trie[0].del(a[i]); trie[1].del(b[i]); } } else { while(pt <= R) { chkmax(maxVal, c[pt]); chkmax(maxVal, trie[0].Squery(b[pt])); chkmax(maxVal, trie[1].Bquery(a[pt])); trie[0].ins(a[pt]); trie[1].ins(b[pt]); pt++; } for(int i = L; i <= BR[o]; i++) { chkmax(maxTmp, c[i]); chkmax(maxTmp, trie[0].Squery(b[i])); chkmax(maxTmp, trie[1].Bquery(a[i])); trie[0].ins(a[i]); trie[1].ins(b[i]); } for(int i = L; i <= BR[o]; i++) { trie[0].del(a[i]); trie[1].del(b[i]); } } ans[id] = max(maxVal, maxTmp); } while(pt > BR[o] + 1) { pt--; trie[0].del(a[pt]); trie[1].del(b[pt]); } } for(int i = 1; i <= m; i++) printf("%d ", ans[i]); return 0; } /* */