两道题都是区间第K大询问,数据规模基本相同。

解决这种问题, 可以采用平方划分(块状表)复杂度也可以接受,但是实际表现比主席树差得多。

这里大致讲一下我对主席树的理解。

首先,如果对于某个区间【L,R】,对这个区间排序后,我们构造出了线段树, 每个值在这个子区间出现了几次都可以从线段树中查询,我们就可以在对数时间解决询问。

现在的问题就是怎样在时空复杂度O(nlogn)的时间内构造出这么多的线段树!


1.首先对原序列a排序并删去重复得到新序列b

2.对a的每个前缀构造线段树,即a的前i个数出现在b的[L,R]中的个数。

3.相邻前缀的线段树只有一条边不同,故每次只需要增加logn个点,总的空间复杂度O(nlogn)

4.前缀线段树的可加性,rt[r]-rt[l-1]就表示了原序列a[l,r]在新序列b[L,R]的数量。

代码很清晰,参照代码和上述4个性质,应该可以很快理解主席树。

一句话总结一下, 在本题中, 主席树就的功能就是快速的告诉我们:

  原序列a的子序列a[l,r]在a排序后的序列b的子序列[L,R]中的个数。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100000 + 5; int a[N], b[N], rt[N * 20], ls[N * 20], rs[N * 20], sum[N * 20]; int n, k, tot, sz, ql, qr, x, q, T; void Build(int& o, int l, int r){
o = ++ tot;
sum[o] = 0;
if(l == r) return;
int m = (l + r) >> 1;
Build(ls[o], l, m);
Build(rs[o], m + 1, r);
} void update(int& o, int l, int r, int last, int p){
o = ++ tot;
ls[o] = ls[last];
rs[o] = rs[last];
sum[o] = sum[last] + 1;
if(l == r) return;
int m = (l + r) >> 1;
if(p <= b[m]) update(ls[o], l, m, ls[last], p);
else update(rs[o], m + 1, r, rs[last], p);
} int query(int ss, int tt, int l, int r, int k){
if(l == r) return l;
int m = (l + r) >> 1;
int cnt = sum[ls[tt]] - sum[ls[ss]];
if(k <= cnt) return query(ls[ss], ls[tt], l, m, k);
else return query(rs[ss], rs[tt], m + 1, r, k - cnt);
} void work(){
scanf("%d%d%d", &ql, &qr, &x);
int ans = query(rt[ql - 1], rt[qr], 1, sz, x);
printf("%d\n", b[ans]);
} int main(){freopen("t.txt","r",stdin);
T=1;
while(T--){
scanf("%d%d", &n, &q);
for(int i = 1; i <= n; i ++) scanf("%d", a + i), b[i] = a[i];
sort(b + 1, b + n + 1);
sz = unique(b + 1, b + n + 1) - (b + 1);
tot = 0;
Build(rt[0],1, sz);
//for(int i = 0; i <= 4 * n; i ++)printf("%d,rt = %d,ls = %d, rs = %d, sum = %d\n", i, rt[i], ls[i], rs[i], sum[i]);
//for(int i = 1; i <= n; i ++)a[i] = lower_bound(b + 1, b + sz + 1, a[i]) - b;
for(int i = 1; i <= n; i ++)update(rt[i], 1, sz, rt[i - 1], a[i]);
// for(int i = 0; i <= 5 * n; i ++)printf("%d,rt = %d,ls = %d, rs = %d, sum = %d\n", i, rt[i], ls[i], rs[i], sum[i]);
while(q --)work();
}
return 0;
}

  

POJ 2104 HDU 2665 主席树 解决区间第K大的更多相关文章

  1. poj 2104 主席树(区间第k大)

    K-th Number Time Limit: 20000MS   Memory Limit: 65536K Total Submissions: 44940   Accepted: 14946 Ca ...

  2. HDU 2665 Kth number(主席树静态区间第K大)题解

    题意:问你区间第k大是谁 思路:主席树就是可持久化线段树,他是由多个历史版本的权值线段树(不是普通线段树)组成的. 具体可以看q学姐的B站视频 代码: #include<cmath> #i ...

  3. poj2104&&poj2761 (主席树&&划分树)主席树静态区间第k大模板

    K-th Number Time Limit: 20000MS   Memory Limit: 65536K Total Submissions: 43315   Accepted: 14296 Ca ...

  4. POJ2104-- K-th Number(主席树静态区间第k大)

    [转载]一篇还算可以的文章,关于可持久化线段树http://finaltheory.info/?p=249 无修改的区间第K大 我们先考虑简化的问题:我们要询问整个区间内的第K大.这样我们对值域建线段 ...

  5. [poj 2104]主席树+静态区间第k大

    题目链接:http://poj.org/problem?id=2104 主席树入门题目,主席树其实就是可持久化权值线段树,rt[i]维护了前i个数中第i大(小)的数出现次数的信息,通过查询两棵树的差即 ...

  6. Super Mario HDU - 4417 (主席树询问区间比k小的个数)

    Mario is world-famous plumber. His “burly” figure and amazing jumping ability reminded in our memory ...

  7. 主席树入门(区间第k大)

    主席树入门 时隔5个月,我又来填主席树的坑了,现在才发现学算法真的要懂了之后,再自己调试,慢慢写出来,如果不懂,就只会按照代码敲,是不会有任何提升的,都不如不照着敲. 所以搞算法一定要弄清原理,和代码 ...

  8. HDU3727--Jewel (主席树 静态区间第k大)

    Jewel Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Subm ...

  9. POJ 2104&HDU 2665 Kth number(主席树入门+离散化)

    K-th Number Time Limit: 20000MS   Memory Limit: 65536K Total Submissions: 50247   Accepted: 17101 Ca ...

随机推荐

  1. Linux 关于umount

    场景:linux下挂载过去的代码目录编译失败.怀疑本地磁盘空间不足问题导致.解决方法:卸载重新挂载. 操作:卸载时报错: 解决方法: 1.umount, 老是提示:device is busy, 服务 ...

  2. python3.x Day5 面向对象

    类:类是指:对具有相同属性的事物的抽象.蓝图.原型.在类中定义了这些事物都具备的属性和共同的方法. 对象:一个对象就是一个类实例化以后的实例,一个类必须经过实例化后才能在程序中被使用,一个类可以实例化 ...

  3. mvc 下 使用kindeditor 配置信息

    先去下载: http://code.google.com/p/kindeditor/downloads/list引用: LitJSON.dll文件<script src="~/kind ...

  4. [USACO12FEB]附近的牛Nearby Cows

    题目描述 Farmer John has noticed that his cows often move between nearby fields. Taking this into accoun ...

  5. 【HDOJ5714】拍照(线性扫描)

    题意:小明在旅游的路上看到了一条美丽的河,河上有许多船只,有的船只向左航行,有的船只向右航行.小明希望拍下这一美丽的风景,并且把尽可能多的船只都完整地拍到一张照片中. 小明位于河的边上,并且可以在河边 ...

  6. jquery判断单选按钮radio是否选中的方法

    JQuery控制radio选中和不选中方法总结 一.设置选中方法 复制代码代码如下: $("input[name='名字']").get(0).checked=true; $(&q ...

  7. MVC view页面需要多个model,复杂网页的处理

    需求描述 一个比较复杂的页面,界面中包含的元素数据来自于许多个有关联或者无关联的表,然后我们要做的就是将数据呈现在界面上. 10年前大概都是这么干的 直接写一个复杂的SQL语句,返回一个包含所需数据的 ...

  8. 使用JavaMail通过QQ/126服务器服务发送邮件

    https://blog.csdn.net/yidragon88xx/article/details/53230310

  9. hdu - 1394 Minimum Inversion Number(线段树水题)

    http://acm.hdu.edu.cn/showproblem.php?pid=1394 很基础的线段树. 先查询在更新,如果后面的数比前面的数小肯定会查询到前面已经更新过的值,这时候返回的sum ...

  10. MongoDB小结02 - 配置、启动MongoDB

    下载MongoDB 第一步:登上MongoDB官网,找到自己的适合的版本下载 第二步:解压(免安装),改名mongodb(举例命名,可以任个人喜好),放在你喜欢的位置(任喜好) 第三步:通过命令行: ...