热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

火星商店问题:线段树分治与持久化Trie树的应用

本题涉及编号为1至n的火星商店,每个商店有一个永久商品价值v。操作包括每天在指定商店增加一个新商品,以及查询某段时间内某些商店中所有商品(含永久商品)与给定密码值的最大异或结果。通过线段树分治和持久化Trie树来高效解决此问题。
### 问题描述
在一个火星上有编号为1到n的商店,每个商店有一个初始的永久商品价值v。题目包含两种操作:

- **操作1**:时间过了一天,第x个商店增加了一个价值为val的新商品。
- **操作2**:给定一个密码值x,询问从第L个商店到第R个商店,在当前天-d+1到当前天的所有商品中(包括永久商品),与密码值x的最大异或结果。

### 解决方案
最大异或值的问题可以通过持久化Trie树来解决。首先,我们需要将每个商店的永久商品价值提前更新到Trie树中。

#### 构建时间线段树
我们构建一棵时间线段树,并将所有的查询操作按时间顺序插入到这棵树中。具体步骤如下:

1. **初始化**:将所有商店的永久商品价值提前更新到Trie树中。
2. **时间线段树**:将所有查询操作按时间顺序插入到线段树中。
3. **CDQ分治**:对操作进行CDQ分治处理,确保操作按时间顺序正确执行。
4. **排序**:为了保证持久化Trie树的有序性,需要对操作按照商店编号进行排序。
5. **处理非连续编号**:由于商店编号可能不连续,因此需要用一个映射来维护持久化Trie树中的节点编号。

### 代码实现
```cpp
#include
using namespace std;

#define rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define repp(i, a, b) for (int i = (a); i >= (b); --i)
#define ll long long
#define see(x) (cerr <<(#x) <<"=" <<(x) <#define inf 0x3f3f3f3f
#define CLR(A, v) memset(A, v, sizeof A)

const int N = 1e5 + 10;
int t[N <<5][2], T[N], siz[N <<5], ncnt, b[N];

void upnode(int k, int x, int pre, int &pos) {
pos = ++ncnt;
t[pos][0] = t[pre][0];
t[pos][1] = t[pre][1];
siz[pos] = siz[pre] + 1;
if (k <0) return;
int c = (x >> k) & 1;
upnode(k - 1, x, t[pre][c], t[pos][c]);
}

int qmax(int k, int x, int pre, int pos) {
if (k <0) return 0;
int c = (x >> k) & 1;
if (siz[t[pos][c ^ 1]] - siz[t[pre][c ^ 1]] > 0)
return (1 < else
return qmax(k - 1, x, t[pre][c], t[pos][c]);
}

vector node[N <<2];
int n, m, ans[N];

void addnode(int x, int L, int R, int l, int r, int pos) {
if (L > R) return;
if (L <= l && r <= R) {
node[pos].push_back(x);
return;
}
int m = (l + r) >> 1;
if (L <= m) addnode(x, L, R, l, m, pos <<1);
if (R > m) addnode(x, L, R, m + 1, r, pos <<1 | 1);
}

struct marspeo {
int L, R, s, t, x;
} peo[N];

struct upp {
int t, x, val;
} up[N], s1[N], s2[N];

int cnt1, cnt0;

void calc(int L, int R, int pos) {
int nn = 0;
ncnt = 0;
rep(i, L, R) {
nn++;
b[nn] = up[i].x;
upnode(20, up[i].val, T[nn - 1], T[nn]);
}
for (auto v : node[pos]) {
int l = lower_bound(b + 1, b + 1 + nn, peo[v].L) - b;
int r = upper_bound(b + 1, b + 1 + nn, peo[v].R) - b - 1;
int temp = qmax(20, peo[v].x, T[l - 1], T[r]);
ans[v] = max(ans[v], temp);
}
}

void cdq(int L, int R, int l, int r, int pos) {
if (L > R) return;
calc(L, R, pos);
if (l == r) return;
int temp1 = 0, temp2 = 0, mid = (l + r) >> 1;
rep(i, L, R)
if (up[i].t <= mid)
s1[++temp1] = up[i];
else
s2[++temp2] = up[i];
rep(i, 1, temp1) up[i + L - 1] = s1[i];
rep(i, 1, temp2) up[i + L + temp1 - 1] = s2[i];
cdq(L, L + temp1 - 1, l, mid, pos <<1);
cdq(L + temp1, R, mid + 1, r, pos <<1 | 1);
}

int main() {
scanf("%d%d", &n, &m);
int x, l, r, op, d;
rep(i, 1, n) {
scanf("%d", &x);
upnode(20, x, T[i - 1], T[i]);
}
while (m--) {
scanf("%d", &op);
if (!op) {
scanf("%d%d", &l, &r);
cnt0++;
up[cnt0] = (upp){cnt0, l, r};
} else {
scanf("%d%d%d%d", &l, &r, &x, &d);
peo[++cnt1] = (marspeo){l, r, max(1, cnt0 - d + 1), cnt0, x};
ans[cnt1] = qmax(20, x, T[l - 1], T[r]);
}
}
rep(i, 1, cnt1) addnode(i, peo[i].s, peo[i].t, 1, cnt0, 1);
sort(up + 1, up + 1 + cnt0, [](upp a, upp b) { return a.x cdq(1, cnt0, 1, cnt0, 1);
rep(i, 1, cnt1) printf("%d\n", ans[i]);
return 0;
}
```

推荐阅读
  • 本文探讨了如何在模运算下高效计算组合数C(n, m),并详细介绍了乘法逆元的应用。通过扩展欧几里得算法求解乘法逆元,从而实现除法取余的计算。 ... [详细]
  • Splay Tree 区间操作优化
    本文详细介绍了使用Splay Tree进行区间操作的实现方法,包括插入、删除、修改、翻转和求和等操作。通过这些操作,可以高效地处理动态序列问题,并且代码实现具有一定的挑战性,有助于编程能力的提升。 ... [详细]
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • 扫描线三巨头 hdu1928hdu 1255  hdu 1542 [POJ 1151]
    学习链接:http:blog.csdn.netlwt36articledetails48908031学习扫描线主要学习的是一种扫描的思想,后期可以求解很 ... [详细]
  • 本题涉及一棵由N个节点组成的树(共有N-1条边),初始时所有节点均为白色。题目要求处理两种操作:一是改变某个节点的颜色(从白变黑或从黑变白);二是查询从根节点到指定节点路径上的第一个黑色节点,若无则输出-1。 ... [详细]
  • Codeforces Round #566 (Div. 2) A~F个人题解
    Dashboard-CodeforcesRound#566(Div.2)-CodeforcesA.FillingShapes题意:给你一个的表格,你 ... [详细]
  • 本文探讨了如何在给定整数N的情况下,找到两个不同的整数a和b,使得它们的和最大,并且满足特定的数学条件。 ... [详细]
  • 题目Link题目学习link1题目学习link2题目学习link3%%%受益匪浅!-----&# ... [详细]
  • 本题通过将每个矩形视为一个节点,根据其相对位置构建拓扑图,并利用深度优先搜索(DFS)或状态压缩动态规划(DP)求解最小涂色次数。本文详细解析了该问题的建模思路与算法实现。 ... [详细]
  • python的交互模式怎么输出名文汉字[python常见问题]
    在命令行模式下敲命令python,就看到类似如下的一堆文本输出,然后就进入到Python交互模式,它的提示符是>>>,此时我们可以使用print() ... [详细]
  • Java 中的 BigDecimal pow()方法,示例 ... [详细]
  • 使用 Azure Service Principal 和 Microsoft Graph API 获取 AAD 用户列表
    本文介绍了一段通用代码示例,该代码不仅能够操作 Azure Active Directory (AAD),还可以通过 Azure Service Principal 的授权访问和管理 Azure 订阅资源。Azure 的架构可以分为两个层级:AAD 和 Subscription。 ... [详细]
  • 本文详细介绍了如何构建一个高效的UI管理系统,集中处理UI页面的打开、关闭、层级管理和页面跳转等问题。通过UIManager统一管理外部切换逻辑,实现功能逻辑分散化和代码复用,支持多人协作开发。 ... [详细]
  • 本文详细介绍了Java中的访问器(getter)和修改器(setter),探讨了它们在保护数据完整性、增强代码可维护性方面的重要作用。通过具体示例,展示了如何正确使用这些方法来控制类属性的访问和更新。 ... [详细]
  • 基于KVM的SRIOV直通配置及性能测试
    SRIOV介绍、VF直通配置,以及包转发率性能测试小慢哥的原创文章,欢迎转载目录?1.SRIOV介绍?2.环境说明?3.开启SRIOV?4.生成VF?5.VF ... [详细]
author-avatar
小呀么小果冻
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有