洛谷 P4585 [FJOI2015]火星商店问题 题解

一、题目:

洛谷原题

二、思路:

此题题意非常毒瘤,看完题根本不知道他在说什么。建议大家看看这个帖子

然后讲一下这道题该怎么做。其实挺容易想到正解的。

首先考虑那些“永久性的商品”。我们发现这就是一个“可持久化Trie树”的板子题。大家可以看一下洛谷P4735 最大异或和。我也有一篇博客

然后考虑那些在某个时间才会出现的商品。考虑用线段树对时间进行分治。那么某个时间出现商品就相当于单点修改。而查询就相当于区间询问。其实一个询问就相当于标记永久化。我们记录一个vector数组\(vec\)\(vec\)表示从线段树的根到当前节点的路径上的询问的集合。每次访问到叶子结点时(其实就对应着单点修改),依次扫描\(vec\)中的每个询问,用该点的修改更新询问的答案即可。

三、代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>

using namespace std;

inline int read(void) {
    int x = 0, f = 1; char ch = getchar();
    while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    return f * x;
}

const int maxn = 1e5 + 5, maxm = 20;

int n, m, a[maxn], day;
int ans[maxn], sz, root[maxn];
int L[maxn << 2], R[maxn << 2];

struct Node {
    int to[2];
    int cnt[2];
} node[2000000];

struct Upd {
    int s, v;
} upd[maxn];

struct Query {
    int l, r, L, R, x, id;
} q[maxn];

struct Gch {
    int l, r, x, id;
    Gch() {}
    Gch(int _l, int _r, int _x, int _id) : l(_l), r(_r), x(_x), id(_id) {}
};

vector<Gch>gch[maxn << 2];
vector<Gch>vec;

inline int call(int x, int i) { return (x >> i) & 1; }

inline void chkmax(int& x, int y) {
    x = y > x ? y : x;
}

inline void init(void) {
    root[0] = 1; sz = 1;
    int p = 1;
    for (int i = 18; i >= 0; --i) {
        node[p].to[0] = ++sz;
        node[p].cnt[0] = 1;
        p = node[p].to[0];
    }
}

inline int insert(int x, int fr) {
    int p = fr, q = ++sz, syb = q;
    for (int i = 18; i >= 0; --i) {
        int now = call(x, i);
        if (p) node[q] = node[p];
        node[q].to[now] = ++sz;
        node[q].cnt[now] = node[p].cnt[now] + 1;
        p = node[p].to[now];
        q = node[q].to[now];
    }
    return syb;
}

inline int query(int l, int r, int x) {
    int p = root[l], q = root[r], res = 0;
    for (int i = 18; i >= 0; --i) {
        int now = call(x, i);
        if (node[q].cnt[now ^ 1] - node[p].cnt[now ^ 1] > 0) {
            res |= (1 << i);
            p = node[p].to[now ^ 1];
            q = node[q].to[now ^ 1];
        }
        else {
            p = node[p].to[now];
            q = node[q].to[now];
        }
    }
    return res;
}

#define lson (o << 1)
#define rson (o << 1 | 1)

void build(int o, int l, int r) {
    L[o] = l; R[o] = r;
    if (l == r) { return; }
    int mid = (l + r) >> 1;
    build(lson, l, mid); build(rson, mid + 1, r);
}

void update(int o, int ql, int qr, const Gch& css) {
    if (ql <= L[o] && R[o] <= qr) { gch[o].push_back(css); return; }
    int mid = (L[o] + R[o]) >> 1;
    if (ql <= mid) update(lson, ql, qr, css);
    if (qr > mid) update(rson, ql, qr, css);
}

void dfs(int o) {
    for (auto& p : gch[o]) vec.push_back(p);
    if (L[o] == R[o]) {
        for (auto& p : vec) {
            if (p.l <= upd[L[o]].s && upd[L[o]].s <= p.r) {
                chkmax(ans[p.id], p.x ^ upd[L[o]].v);
            }
        }
        for (int i = 1; i <= (int)gch[o].size(); ++i) vec.pop_back();
        return;
    }
    dfs(lson);
    dfs(rson);
    for (int i = 1; i <= (int)gch[o].size(); ++i) vec.pop_back();
}

int main() {
    n = read(); m = read();
    init();
    for (int i = 1; i <= n; ++i) {
        a[i] = read();
        root[i] = insert(a[i], root[i - 1]);
    }
    int num = 0;
    for (int i = 1; i <= m; ++i) {
        int opt = read();
        if (opt == 0) {
            ++day;
            upd[day].s = read();
            upd[day].v = read();
        }
        else if (opt == 1) {
            if (i == 1) ++day;
            ++num;
            q[num].l = read(); q[num].r = read(); q[num].x = read();
            int d = read();
            q[num].R = day;
            q[num].L = day - d + 1;
            q[num].id = num;
            ans[num] = query(q[num].l - 1, q[num].r, q[num].x);
        }
    }
    build(1, 1, day);
    for (int i = 1; i <= num; ++i) {
        if (q[i].L <= q[i].R)
            update(1, q[i].L, q[i].R, Gch(q[i].l, q[i].r, q[i].x, q[i].id));
    }
    dfs(1);
    for (int i = 1; i <= num; ++i)
        printf("%d\n", ans[i]);
    return 0;
}
posted @ 2021-04-05 15:49  蓝田日暖玉生烟  阅读(123)  评论(1编辑  收藏  举报