动态区间第k小(主席树+线段树套树状数组)

静态区间第k小问题,是给你一个序列,每次询问序列中的一个区间中的第k小数,这个问题用普通的主席树就可以解决。动态区间第k小问题就是在静态的基础上加上了修改操作,也就是每次除了询问区间第k小之外,还可以修改序列中的某个数。因为这里涉及到了修改操作,我们用只用主席树好像难以完成这个问题,下面我们简单来分析一下这个问题。
我们知道在主席树中,第i棵线段树T[i]维护的是序列[1,i]中的数,我们设想一下,如果我们修改一个数,那么这个修改将影响到的线段树有T[i], T[i + 1] … ..T[n],如果我们用普通暴力的方法,每次都更新所有的这些线段树,那么时间复杂度爆表,这种做法肯定是不可行的。那么我们要想另外一种比O(n)更新还快的操作来解决这个问题。我们分析主席树的性质可以得到,如果修改了一个树,对那些线段树的影响都是一样的,比如,序列中原来位置i上的数是x,现在我们把它修改成y,那么对于需要修改的线段树,T[i], T[i + 1]…….T[n],每棵线段树的影响都是对应线段树上减去了数x,加上了数y,到了这里我们可以联想到树状数组,好像可以优化这个操作。我们让树状数组上的每个点对应一棵线段树,第i棵线段树维护区间[i - lowbit(i) + 1, i]区间的变化量就行。

下面是zoj2212的ac代码(第一次写数据结构套数据结构,写的比较丑):

#include<bits/stdc++.h>
using namespace std;
const int maxn = 6e4 + 10;
int n, q;
struct node{
    int L, R;
    int sum;
    node(){
        sum = 0;
    }
}Tree[2500010];//线段树的节点
int cnt;
int s[maxn];//树状数组,每个点表示一颗线段树的根节点
int X[maxn], Y[maxn];//辅助数组
int T[maxn];//第i棵线段树的根节点
int a[maxn];//原数组
int H[maxn];//原数组排序之后的数组
int m;//总共不同数的个数,也就是每棵线段树的大小
struct ask{
    int l, r;
    int k;
}Ask[maxn];//由于要整体先hash,所以必须离线处理
void init()
{
    cnt = <
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值