Codeforces 620F Xors on Segments 回滚莫队 + 字典树 || 离心询问分治 + 可持久化字典树
Posted cjlhy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 620F Xors on Segments 回滚莫队 + 字典树 || 离心询问分治 + 可持久化字典树相关的知识,希望对你有一定的参考价值。
转换一下变成询问区间选两个数异或的最大值, 要注意的是一个数作为左端点要-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(Qusl, 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\n", ans[i]); return 0; /* */
以上是关于Codeforces 620F Xors on Segments 回滚莫队 + 字典树 || 离心询问分治 + 可持久化字典树的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #198 (Div. 1) D. Iahub and Xors 二维树状数组*
Iahub and Xors Codeforces - 341D
CodeForces 1292C Xenon's Attack on the Gangs
Codeforces Round #614 (Div. 2) E. Xenon's Attack on the Gangs
模拟ECNA 2015 I What's on the Grille? (Codeforces GYM 100825)
Codeforces Round #614 (Div. 2) E. Xenon's Attack on the Gangs