码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2019-06-18 21:28:38      阅读:109      评论:0      收藏:0      [点我收藏+]

标签:problems   个数   i++   color   bool   mes   ORC   continue   --   

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\n", ans[i]);
    return 0;
}

/*
*/

 

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

标签:problems   个数   i++   color   bool   mes   ORC   continue   --   

原文地址:https://www.cnblogs.com/CJLHY/p/11047745.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!