『学习笔记』树套树(todo)
维护一个序列:
- 单点修改。
- 给定 \(x\),查询区间有多少个位置 \(i\) 满足 \(a_i=x\)。
线段树套 map,可以 \(O(\log)\)。哈希表?\(O(1)\)。
树状数组套 map:
map<int,int> t[N];
int find(int x,int y){
// 查询 [1,x] 中 y 出现次数
int ans=0;
for(int i=x; i; i-=lowbit(i))
ans+=t[i][y];
return ans;
}
void insert(int x,int y){
// 在 x 位置插入 y
for(int i=x; i<=n; i+=lowbit(i))
t[i][x]--,t[i][y]++;
}
如果把询问改为 \(a_i<x\)?
平衡树 t[N];
// 或者 线段树 t[N];
int find(int x,int y){
// 查询 [1,x] 中 <y 个数
int ans=0;
for(int i=x; i; i-=lowbit(i))
ans+=t[i].find(y);
return ans;
}
void insert(int x,int y){
// 在 x 位置插入 y
for(int i=x; i<=n; i+=lowbit(i))
t.insert(y);
}
树状数组套平衡树/线段树/...,即树套树。
可以解决动态二维数点。
树套树难点在于维护内层数据结构。
P4396 [AHOI2013] 作业
三维数点。树套树 / cdq 分治。
P3157 [CQOI2011] 动态逆序对
考虑每删一个点的影响,转化为区间查询和单点删除。
P4690 [Ynoi2016] 镜子里的昆虫 (弱化版)
- 单点修改。
- 询问区间出现了多少种不同的数。
维护 \(pre_i\) 表示 \(i\) 之前第一个与 \(i\) 相同的数,询问即 \(pre_i<l(i \in[l,r])\) 个数。
对于修改,只会影响 \(O(1)\) 个元素。考虑用 set 维护每钟值存在的下标,二分找一下修改即可。
P4690 [Ynoi2016] 镜子里的昆虫
- 区间修改。
- 询问区间出现了多少种不同的数。
同样维护 \(pre_i\),颜色段均摊。对于修改覆盖的每一个颜色段,仅左端点的 \(pre_i\) 会改变。
树状数组维护,\(O(\log)\)。
P3242 [HNOI2015] 接水果
考虑每个盘子 \((x,y,k)\) 的贡献,只有 \(x\) 与 \(y\) 子树内的两个点连成的路径合法,那么拍成 dfn,可以转化为矩阵 \(+k\)。询问即可转化为单点覆盖矩形 kth。树状数组上差分,转化为单点修改区间查询。套一个值域线段树求 kth,方便二分。

浙公网安备 33010602011771号