POJ 2104 HDU 2665 主席树 解决区间第K大
两道题都是区间第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大的更多相关文章
- poj 2104 主席树(区间第k大)
K-th Number Time Limit: 20000MS Memory Limit: 65536K Total Submissions: 44940 Accepted: 14946 Ca ...
- HDU 2665 Kth number(主席树静态区间第K大)题解
题意:问你区间第k大是谁 思路:主席树就是可持久化线段树,他是由多个历史版本的权值线段树(不是普通线段树)组成的. 具体可以看q学姐的B站视频 代码: #include<cmath> #i ...
- poj2104&&poj2761 (主席树&&划分树)主席树静态区间第k大模板
K-th Number Time Limit: 20000MS Memory Limit: 65536K Total Submissions: 43315 Accepted: 14296 Ca ...
- POJ2104-- K-th Number(主席树静态区间第k大)
[转载]一篇还算可以的文章,关于可持久化线段树http://finaltheory.info/?p=249 无修改的区间第K大 我们先考虑简化的问题:我们要询问整个区间内的第K大.这样我们对值域建线段 ...
- [poj 2104]主席树+静态区间第k大
题目链接:http://poj.org/problem?id=2104 主席树入门题目,主席树其实就是可持久化权值线段树,rt[i]维护了前i个数中第i大(小)的数出现次数的信息,通过查询两棵树的差即 ...
- Super Mario HDU - 4417 (主席树询问区间比k小的个数)
Mario is world-famous plumber. His “burly” figure and amazing jumping ability reminded in our memory ...
- 主席树入门(区间第k大)
主席树入门 时隔5个月,我又来填主席树的坑了,现在才发现学算法真的要懂了之后,再自己调试,慢慢写出来,如果不懂,就只会按照代码敲,是不会有任何提升的,都不如不照着敲. 所以搞算法一定要弄清原理,和代码 ...
- HDU3727--Jewel (主席树 静态区间第k大)
Jewel Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Subm ...
- POJ 2104&HDU 2665 Kth number(主席树入门+离散化)
K-th Number Time Limit: 20000MS Memory Limit: 65536K Total Submissions: 50247 Accepted: 17101 Ca ...
随机推荐
- 输出一定范围unicode对应符号
#本程序没有考虑对0x的处理,请勿输入,直接输入16进制位即可 begin = input("起始点:") end = input("结束点:") b_int0 ...
- LeetCode(6) ZigZag Conversion
题目 The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows li ...
- JS判断滚动条是否停止滚动
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Leetcode 213.大家劫舍II
打家劫舍II 你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金.这个地方所有的房屋都围成一圈,这意味着第一个房屋和最后一个房屋是紧挨着的.同时,相邻的房屋装有相互连通的防盗系统,如果两 ...
- Leetcode 207.课程表
课程表 现在你总共有 n 门课需要选,记为 0 到 n-1. 在选修某些课程之前需要一些先修课程. 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们: [0,1] 给定课程总 ...
- CentOS下LVS DR模式负载均衡配置详解
一安装LVS准备: 1.准备4台Centos 6.2 x86_64 注:本实验关闭 SELinux和IPtables防火墙. 管理IP地址 角色 备注 192.168.1.101 LVS主调度器(Ma ...
- Just a Hook-HDU1698(线段树求区间)
http://acm.hdu.edu.cn/showproblem.php?pid=1698 Problem Description In the game of DotA, Pudge’s meat ...
- mybatis最重要的mapper文件书写
1.MyBatis中在查询进行select映射的时候,返回类型可以用resultType,也可以用resultMap. 也只有在mapper的select标签中,才会指定resultMap属性的值,其 ...
- [React] Build a slide deck with mdx-deck using Markdown + React
In this lesson we'll use mdx-deck to create a slide deck using Markdown and React. We'll look at add ...
- matlab Newton method
% Matlab script to illustrate Newton's method % to solve a nonlinear equation % this particular scri ...