• 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(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;
    }
    
    /*
    */
  • 相关阅读:
    SM2实现(利用openssl的evp)
    BouncyCastle的SM实践
    初步动态分析
    信安保障复习
    数据库实验3
    软件测试之测试用例设计题
    Spring SPI 机制总结
    Servlet与Netty横向对比
    被遮挡部分高亮
    (十一)Android环境变量设置
  • 原文地址:https://www.cnblogs.com/CJLHY/p/11047745.html
Copyright © 2020-2023  润新知