Codeforces 620F Xors on Segments 回滚莫队 + 字典树 || 离心询问分治 + 可持久化字典树

Posted cjlhy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 620F Xors on Segments 回滚莫队 + 字典树 || 离心询问分治 + 可持久化字典树相关的知识,希望对你有一定的参考价值。

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