P3834 【模板】可持久化线段树 2(主席树)

我们详细讲讲这个整体二分如何求区间第k小
我们都知道二分可以求出区间里某个想要的值,如果有很多询问,我们对每个询问都进行二分,复杂度就是O(QNlog(1e9))铁超,那怎么优化呢?
我们先看第一个图
对于7个数的区间[1,5,2,6,3,7,4],我们有两个询问,[2,5]的第3小,[4,4]的第1小
我们先对区间[2,5]进行二分,会得到:
[1,7] mid=4 n=2<3,(这里3是我们要求的第3小数,2指的是区间[2,5]内<=mid的数量)
[5,7] mid=6 n=4>=3(以下同里)
[5,6] mid=5 n=3 >=3
[5,5]->(l == r)ans = 5
然后我们对区间[4,4]二分,也会得到差不多的过程:
[1,7] mid=4 n=0<1
[5,7] mid=6 n=1>=1
[5,6] mid=5 n=0<1
[6,6]–>ans=6
我们刚才说过对于每个区间二分是不行的,因为会超时,现在我们对这两个过程进行对比,发现有大量过程是在同一个而区间进行的,都会到[1,7],[5,7],[5,6]这三个区间,所以整体二分的含义就是将所有区间当作一个整体二分。

现在看图2:
数组[1,5,2,6,3,7,4]
我们现在要进行三次查询,分别是:
[2,5] 3
[4,4] 1
[1,7] 3
我们现在开始模拟过程:
一开始二分区间[1,7] mid=4
[2,5] K=3 n=2<K
[4,4] K=1 n=0<K
[1,7] K=3 n=4>=K
n<mid的向右继续寻找,n>=mid向右寻找
[1,7] K=3就向左找,此时寻找区间就变成[1,4] mid=2 ,此时n=2<K,向右找,一直到区间左右一样
[2,5]和[4,4]向右找,向右找时K是要减去n的,相当于左边已经有n个小于K的值,我们去右边只需要找第K-n的值就可以了
此时区间为[5,7]mid=6
[2,5] K=1 n=2>=K
[4,4] K=1 n=1>=K
继续上述过程
最终会形成一个类似树的结构,看看图就知道了,这样复杂度就优化了
n的计算要用得到树状数组
复杂度为:O(QlogNlog(1e9))
logN为树状数组,log(1e9)为二分

代码中的lq和rq数组就是将在每次二分中,将询问区间分成两部分,就如图2中将
[2,5] K=3 n=2<K
[4,4] K=1 n=0<K
[1,7] K=3 n=4>=K
这三个操作,将前两个分为一组,第三个分为另一组

代码:

#pragma optimize("Ofast")
#include<bits/stdc++.h>
#define MAXN 400005
#define inf int(1e9)
using namespace std;
typedef long long ll;int N,M;
struct Node{int op,x,y,k;//op=insert+1/remove-1,query2int id;Node(int op=0, int x=0, int y=0, int k=0, int id=0):op(op), x(x), y(y), k(k), id(id){}
} q[MAXN],lq[MAXN],rq[MAXN];//
int fw[MAXN];
inline int lbt(int x){return x&(-x);
}inline void change(int x, int dv){for(;x<=N;x+=lbt(x)){fw[x] += dv;}
}inline int query(int x){int ans = 0;for(;x>0;x-=lbt(x)){ans += fw[x];}return ans;
}
//
int ANS[MAXN];void solve(int vl, int vr, int ql, int qr){//cerr<<"solve: "<<vl<<" "<<vr<<" "<<ql<<" "<<qr<<endl;if(ql > qr) return;if(vl == vr){for(int i=ql;i<=qr;i++){if(q[i].op==2) ANS[q[i].id] = vl;}return;}//insertint mid = (vl + vr)>>1;int nl = 0, nr = 0;for(int i=ql;i<=qr;i++){if(q[i].op != 2){//insert/removeif(q[i].x <= mid) change(q[i].y, q[i].op), lq[++nl] = q[i];else rq[++nr] = q[i];}else{//queryint n = query(q[i].y) - query(q[i].x-1);if(q[i].k <= n) lq[++nl] = q[i];else{q[i].k -= n;rq[++nr] = q[i];}}}//removefor(int i=ql;i<=qr;i++){if(q[i].op != 2){if(q[i].x <= mid) change(q[i].y, -q[i].op);}}for(int i=1;i<=nl;i++) q[ql+i-1] = lq[i];for(int i=1;i<=nr;i++) q[ql+nl+i-1] = rq[i];solve(vl, mid, ql, ql+nl-1);solve(mid+1, vr, ql+nl, qr);
}int main(){scanf("%d%d", &N, &M);int x,l,r,k;;for(int i=1;i<=N;++i){scanf("%d", &x);q[i] = Node(1,x,i);}for(int i=1;i<=M;i++){scanf("%d%d%d", &l, &r, &k);q[N+i] = Node(2,l,r,k,i);}solve(-1e9,1e9,1,N+M);for(int i=1;i<=M;i++){printf("%d\n", ANS[i]);}return 0;
}

P3834 【模板】可持久化线段树 2(整体二分做法)相关推荐

  1. 解题报告:P3834 【模板】可持久化线段树 2(主席树)详解

    P3834 [模板]可持久化线段树 2(主席树) 题解 P3834 [[模板]可持久化线段树 2(主席树)] 1)静态求第k大数 可持久化线段树,不能用堆的方法存子结点了,所以用指针l表示左儿子r表示 ...

  2. 【用学校抄作业带你走进可持久化线段树(主席树)】可持久化线段树概念+全套模板+例题入门:[福利]可持久化线段树)

    我似乎很少写这种算法博客 可持久化线段树概念 概念介绍(类比帮助理解) 简单分析一下时间和空间复杂度(内容池) 模板 结构体变量 建树模板 单点修改模板 单点查询模板 区间修改模板(pushup) 区 ...

  3. 【模板】可持久化线段树

    可持久化线段树/主席树: 顾名思义,该数据结构是可以访问历史版本的线段树.用于解决需要查询历史信息的区间问题. 在功能与时间复杂度上与开n棵线段树无异,然而空间复杂度从$O(n\times nlogn ...

  4. P3834-【模板】可持久化线段树 1(主席树)

    正题 评测记录:https://www.luogu.org/recordnew/lists?uid=52918&pid=P3834 题意 给定一个长度为n的序列,有m个询问,求一个区间内的第k ...

  5. 【模板】可持久化线段树 1(主席树)

    题目背景 这是个非常经典的主席树入门题--静态区间第K小 数据已经过加强,请使用主席树.同时请注意常数优化 题目描述 如题,给定N个正整数构成的序列,将对于指定的闭区间查询其区间内的第K小值. 输入输 ...

  6. LGOJ P3919【模板】可持久化数组(可持久化线段树/平衡树)

    代码 //可持久化线段树 #include <cstdio> using namespace std;struct node {node *Lnode,*Rnode;int val;voi ...

  7. P3919 【模板】可持久化数组(可持久化线段树/平衡树)(入门第一题)

    学习博客:http://www.cnblogs.com/flashhu/p/8297581.html 题目链接:https://www.luogu.org/problemnew/show/P3919 ...

  8. 主席树 - 可持久化线段树

    模板 P3834 [模板]可持久化线段树 2(主席树) 区间求第 \(k\) 大 模板代码 #include<bits/stdc++.h> using namespace std; #de ...

  9. 【可持久化线段树?!】rope史上最全详解

    https://www.luogu.org/problemnew/show/P3919 看到上面链接中的题时,我在学会可持久化线段树的同时,第一次学会了一个非常屌(cai)的STL大法--rope!! ...

最新文章

  1. 开发日记 20200129 新年这几天的总结
  2. Java初学者如何迈出AOP第一步--使用Java 动态代理实现AOP
  3. apache+Tomcat均衡负载配置
  4. ACM-ICPC 2019 山东省省赛 C Wandering Robot
  5. java io运用_Java IO相关使用
  6. mysql数据异常增长_mysql表到一定数据量后会异常的增长
  7. 自定义标签之 带Body的标签库
  8. lc 297. Serialize and Deserialize Binary Tree
  9. 资深架构师谈云原生生态的基石Kubernetes
  10. Java面试题分享,这份资料包你值得拥有!
  11. 一个迅雷480M,是搞笑的吗?
  12. oracle磁带库清洁带标签,分享那些在磁带库上爬过的坑
  13. 全网显示 IP 归属地,是怎么实现的?
  14. Fiddler模拟网络波动_xing2516_新浪博客
  15. vue 高德地图点击获取坐标与地理位置
  16. 访问服务器上的图片显示404,vue run build打包之后服务器端访问图片404
  17. uni-app实战之社区交友APP(20)兼容处理和打包上线
  18. 谷歌邮箱lmap服务器填什么_SMTP和IMAP是什么?
  19. 微信“小程序”来了,短期不可高估,长期不可低估
  20. 普里姆算法解决修路问题

热门文章

  1. 私房钱就藏在老婆眼皮底下
  2. 变态公式之如何算出圆的内部被切割成几块?
  3. java 数组长度 可变_java基础之集合长度可变的实现原理
  4. java 逐行写入csv_go|使用go读写CSV文件
  5. 单片机c语言位运算写法,单片机与嵌入式系统中C语言的位运算小记
  6. php super和parent,parent()、parents()的用法区别
  7. leetcode24. 两两交换链表中的节点(思路+解析)
  8. 利用vector实现一对一(pair<int,int>)
  9. 手写一个简易bundler打包工具带你了解Webpack原理
  10. C++ 多态实现的三个条件