题目链接


题目大意:

给你一个数组aaa,aaa有两个操作

  1. 询问aaa中[l,r][l,r][l,r]区间里面第kkk小的数是哪个?
  2. 修改axa_xax​为yyy

解题思路:

首先我们知道权值线段树是可以求第kkk小的数的,如果只有第一个问题那么就是一个主席树问题,但是主席树对于第二个问题,要修改nnn棵树时间复杂度是O(nlogn)O(nlogn)O(nlogn)的很大不行

我们知道主席树是怎么建立的?
是root[i]继承了root[i−1]的到的连续区间的权值线段树root[i]继承了root[i-1]的到的连续区间的权值线段树root[i]继承了root[i−1]的到的连续区间的权值线段树
因为你修改一个点你要把影响传到后面的所有的rootrootroot,那么开销很大
那么这个是不是很想树状数组??

树状数组修改的时候只把影响传给了后面的logloglog个节点,每次查询都要去询问logloglog个节点


那么我们的思路就来了,就是树状数组每个节点都是一个动态开点的权值线段树,现在我们要更新a5a_5a5​,那么我们只有更新root[5,6,8,16]root[5,6,8,16]root[5,6,8,16]这4个节点的权值线段树

其实我们发现树状数组的作用是分层,把序列分成了logloglog层,每次这个影响只会传到每一层的一个点去

到时候查询的时候要logloglog个节点一起跳这样才能完整的统计影响


AC code

#include <bits/stdc++.h>
#define mid ((l + r) >> 1)
#define Lson rt << 1, l , mid
#define Rson rt << 1|1, mid + 1, r
#define ms(a,al) memset(a,al,sizeof(a))
#define log2(a) log(a)/log(2)
#define lowbit(x) ((-x) & x)
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define INF 0x3f3f3f3f
#define LLF 0x3f3f3f3f3f3f3f3f
#define endl '\n'
using namespace std;
const int N = 2e6 + 10, mod = 1e9 + 9;
const int maxn = 500010;
const long double eps = 1e-5;
const int EPS = 500 * 500;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
typedef pair<double,double> PDD;
template<typename T> void read(T &x) {x = 0;char ch = getchar();ll f = 1;while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
template<typename T, typename... Args> void read(T &first, Args& ... args) {read(first);read(args...);
}
struct qu {char op[2];int l, r, k;
}q[maxn];
struct node {int lson, rson;int val;
}sgt[maxn * 40];
int n, root[maxn], cnt, m;
int arr[maxn];
vector<int> lis;
inline int getid(int x) {return lower_bound(lis.begin(),lis.end(),x) - lis.begin() + 1;
}inline void pushup(int rt) {sgt[rt].val = sgt[sgt[rt].lson].val + sgt[sgt[rt].rson].val;return;
}inline void insert(int &rt, int l, int r, int pos, int val = 1) {if(!rt) rt = ++ cnt;if(l == r) {sgt[rt].val += val;return;}if(pos <= mid) insert(sgt[rt].lson,l,mid,pos,val);else insert(sgt[rt].rson,mid+1,r,pos,val);pushup(rt);
}int jump[2][30], idx[2];
inline void pre_quary(int l, int r) {idx[0] = idx[1] = 0;while(l) {jump[0][++idx[0]] = root[l];l -= lowbit(l);}while(r) {jump[1][++idx[1]] = root[r];r -= lowbit(r);}
}int quary(int l, int r, int kth) {if(l == r) return l;int lsiz = 0, rsiz = 0;//log个节点一起条for(int i = 1; i <= idx[0]; ++ i)  lsiz += sgt[sgt[jump[0][i]].lson].val;for(int i = 1; i <= idx[1]; ++ i)  rsiz += sgt[sgt[jump[1][i]].lson].val;if(kth <= rsiz - lsiz) {for(int i = 1; i <= idx[0]; ++ i)  jump[0][i] = sgt[jump[0][i]].lson;for(int i = 1; i <= idx[1]; ++ i)  jump[1][i] = sgt[jump[1][i]].lson;return quary(l,mid,kth);        } else {for(int i = 1; i <= idx[0]; ++ i)  jump[0][i] = sgt[jump[0][i]].rson;for(int i = 1; i <= idx[1]; ++ i)  jump[1][i] = sgt[jump[1][i]].rson;return quary(mid+1,r,kth-(rsiz-lsiz));        }
}int main() {IOS;cin >> n >> m;for(int i = 1; i <= n; ++ i) {cin >> arr[i];lis.push_back(arr[i]);} for(int i = 1; i <= m; ++ i){cin >> q[i].op;if(*q[i].op == 'C') cin >> q[i].l >> q[i].r, lis.push_back(q[i].r);else cin >> q[i].l >> q[i].r >> q[i].k;}sort(lis.begin(),lis.end());lis.erase(unique(lis.begin(),lis.end()),lis.end());int len = lis.size() + 1;for(int i = 1; i <= n; ++ i) {arr[i] = getid(arr[i]);//像树状数组一样跟新int j = i;while(j < len) {insert(root[j],1,len,arr[i]);j += lowbit(j);}}for(int i = 1; i <= m; ++ i) {char op = *q[i].op;if(op == 'C') {int ax = q[i].l, y = q[i].r;int j = ax;while(j < len) {insert(root[j],1,len,arr[q[i].l],-1);j += lowbit(j);}  j = ax;arr[q[i].l] = getid(q[i].r);while(j < len) {insert(root[j],1,len,arr[q[i].l],1);j += lowbit(j);}  } else {pre_quary(q[i].l-1,q[i].r);cout << lis[quary(1,len,q[i].k) - 1]  << "\n";}}}

树套树 ---- 树状数组套权值线段树模板题 P2617 Dynamic Rankings 动态第K大相关推荐

  1. [权值线段树]魔道研究

    题目描述 "我希望能使用更多的魔法.不对,是预定能使用啦.最终我要被大家称呼为大魔法使.为此我决定不惜一切努力." --<The Grimoire of Marisa> ...

  2. 树套树 ----- P1975 [国家集训队]排队(树状数组套权值线段树求动态逆序对)

    解题思路: 首先我们知道交换两个数a[l]和a[r]a[l]和a[r]a[l]和a[r]影响到的区间是[l+1,r−1][l+1,r-1][l+1,r−1] 对于a[l]a[l]a[l],我们要减去[ ...

  3. Zju2112 Dynamic Rankings(树状数组套可持久化权值线段树)

    Zju2112 Dynamic Rankings description solution code description 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须 ...

  4. 动态区间第k小:树状数组套权值线段树

    所谓树状数组套权值线段树,就是在树状树组上套权值线段树 (逃) 解析 如何解决静态区间第k小? 使用主席树就ok啦 辣么如何解决动态区间第k小嘞- 我们想想主席树为啥不能解决动态区间第k小 因为如果改 ...

  5. 刷题总结——序列操作(权值线段树套树状数组)

    题目: 题目描述 给出序列 a1,a2,-,an(0≤ai≤109),有关序列的两种操作. 1. ai(1≤i≤n)变成 x(0≤x≤109). 2. 求 al,al+1,-,ar(1≤l≤r≤n)第 ...

  6. 【BZOJ3295】动态逆序对,CDQ分治/BIT套权值线段树

    传送门 思路: 用来练习cdq的题目 断断续续纠结了2天 因为loli一直在考试 最后莫名乱搞了一发就A了? 实际上是考虑每一次修改对答案的贡献,即位置在1~x-1且大于x的数以及位置在x+1~n且小 ...

  7. 数据结构:树套树-替罪羊树套权值线段树

    BZOJ3065 本题是在BZOJ上的处女A,实在不应该拿这样一道题来开头 平衡树套线段树应该是树套树问题里比较难的一种了,当然我记得还有一个替罪羊树套Trie树的题,我是不信自己能写出来的. 外层的 ...

  8. Minimum Inversion Number HDU - 1394(权值线段树/树状数组)

    The inversion number of a given number sequence a1, a2, -, an is the number of pairs (ai, aj) that s ...

  9. bzoj4605 崂山白花蛇草水 权值线段树套kd树

    Description Q次操作,要求资瓷 在(x,y)处放一个数字x 查询(x1,y1)到(x2,y2)矩形内第k大 Solution 非常裸的权值线段树套kd树,为了保证复杂度可以定期重构也可以平 ...

最新文章

  1. SQL与NoSQL区别-存储方式
  2. python中为什么训练数据_python训练数据时打乱训练数据与标签
  3. ISA Server 2006的全自动无人职守安装
  4. 1.Java(初级)编程教程(油管 thenewboston)学习笔记get user input
  5. NJ4X源码阅读分析笔记系列(三)—— nj4x-ts深入分析
  6. Android Studio安装genymotion模拟器
  7. git rebase命令(转)
  8. devops 三十六计_DevOps从业人员应遵循的16个博客和新闻通讯
  9. 当我的生活只剩下写代码时
  10. 酷客多小程序携手Richly network Pte Led正式进军新加坡市场
  11. 《符号学:原理与推演》引论
  12. 经济机器是如何运行的(观后感)
  13. 使用excel2007做聚光灯
  14. photoshop更改图片DPI方法
  15. U8-固定资产月末结账报错:BOF或EOF中有一个是真
  16. F. Elongated Matrix
  17. 数据库课程设计:利用python+MySQL+pyqt5设计一个带UI界面的书店管理系统
  18. 《水浒传》108将的绰号(ZZ)
  19. 巴菲特致股东的一封信:2002年
  20. R语言ROC曲线下的面积 - 评估逻辑回归中的歧视

热门文章

  1. MySQL数据库中的索引
  2. MySQL数据库排序order by(asc、desc)
  3. intellij idea的out目录下为什么会有与src名字相同的.class文件呢?
  4. 生成树协议,stp使用哪两个参数来选举根网桥?
  5. Python 图像处理简介——色彩阴影调整
  6. 干货|卷积有多少种?一文读懂深度学习中的各种卷积
  7. 深度神经网络是否过拟合?
  8. python08-类与对象
  9. 自定义窗体设计器-控件测试
  10. hadoop2 自定义OutputFormat场景杂记