[转载]一篇还算可以的文章,关于可持久化线段树http://finaltheory.info/?p=249

无修改的区间第K大

  • 我们先考虑简化的问题:我们要询问整个区间内的第K大。这样我们对值域建线段树,每个节点记录这个区间所包含的元素个数,建树和查询时的区间范围用递归参数传递,然后用二叉查找树的询问方式即可:即如果左边元素个数sum>=K,递归查找左子树第K大,否则递归查找右子树第K – sum大,直到返回叶子的值。

  • 现在我们要回答对于区间[l, r]的第K大询问。如果我们能够得到一个插入原序列中[1, l – 1]元素的线段树,和一颗插入了[1, r]元素的线段树,由于线段树是开在值域上,区间长度是一定的,所以结构也必然是完全相同的,我们可以直接对这两颗线段树进行相减,得到的是相当于插入了区间[l ,r]元素的线段树。注意这里利用到的区间相减性质,实际上是用两颗不同历史版本的线段树进行相减:一颗是插入到第l-1个元素的旧树,一颗是插入到第r元素的新树。

下面是代码

 #include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; const int maxn = 1e5+;
int A[maxn],B[maxn],mp[maxn],C[maxn]; // A 为原始数组, B为离散化之后的数组
int n,m,tot,c[maxn*],lson[maxn*],rson[maxn*];
int build(int l,int r)
{
int root = tot++;
c[root] = ;
if (l != r)
{
int mid = (l + r) >> ;
lson[root] = build(l,mid);
rson[root] = build(mid+,r);
}
return root;
}
int update(int root,int pos,int val)
{
int newroot = tot++;
int tmp = newroot;
int l = ,r = n;
c[newroot] = c[root] + val;
while (l < r)
{
int mid = (l + r) >> ;
if (pos <= mid)
{
rson[newroot] = rson[root];
root = lson[root];
lson[newroot] = tot++;
newroot = lson[newroot];
r = mid;
}
else
{
lson[newroot] = lson[root];
root = rson[root];
rson[newroot] = tot++;
newroot = rson[newroot];
l = mid + ;
}
c[newroot] = c[root] + val;
}
return tmp;
}
int query(int l_root,int r_root,int k)
{
int l = , r = n;
while (l < r)
{
int mid = (l + r) >> ;
/*if (c[lson[r_root]] - c[lson[l_root]] >= k)
{
l_root = rson[l_root];
r_root = rson[r_root];
r = mid;
}
else
{
k -= (c[rson[r_root]] - c[rson[l_root]]);
r_root = lson[r_root];
l_root = lson[l_root];
l = mid + 1;
}*/ if (c[lson[r_root]] - c[lson[l_root]] >= k)
{
r = mid;
l_root = lson[l_root];
r_root = lson[r_root];
}
else
{
l = mid + ;
k -= c[lson[r_root]] - c[lson[l_root]];
l_root = rson[l_root];
r_root = rson[r_root];
}
}
return l;
}
int per_root[maxn];
int main(void)
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
while (~scanf ("%d%d",&n,&m))
{
tot = ;
for (int i = ; i <= n; i++)
{
scanf ("%d",A+i);
C[i] = A[i];
} sort(A+,A+n+);
n = unique(A + , A + n + ) - A - ; for (int i = ; i <= n; i++)
{
B[i] = lower_bound(A+,A+n+,C[i]) - A ;
mp[B[i]] = C[i];
}
per_root[] = build(,n);
for (int i = ; i <= n; i++)
{
per_root[i] = update(per_root[i-],B[i],);
}
for (int i = ; i < m; i++)
{
int l,r,k;
scanf ("%d%d%d",&l,&r,&k);
printf("%d\n",mp[query(per_root[l-],per_root[r], k)]);
}
}
return ;
}

POJ2104-- K-th Number(主席树静态区间第k大)的更多相关文章

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

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

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

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

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

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

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

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

  5. 洛谷.3834.[模板]可持久化线段树(主席树 静态区间第k小)

    题目链接 //离散化后范围1~cnt不要错 #include<cstdio> #include<cctype> #include<algorithm> //#def ...

  6. A - 低阶入门膜法 - K-th Number (主席树查询区间第k小)

    题目链接:https://cn.vjudge.net/contest/284294#problem/A 题目大意:主席树查询区间第k小. 具体思路:主席树入门. AC代码: #include<i ...

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

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

  8. 主席树--动态区间第k小

    主席树--动态区间第\(k\)小 模板题在这里洛谷2617. 先对几个问题做一个总结: 阅读本文需要有主席树的基础,也就是通过区间kth的模板题. 静态整体kth: sort一下找第k小,时间复杂度\ ...

  9. HDU 5919 - Sequence II (2016CCPC长春) 主席树 (区间第K小+区间不同值个数)

    HDU 5919 题意: 动态处理一个序列的区间问题,对于一个给定序列,每次输入区间的左端点和右端点,输出这个区间中:每个数字第一次出现的位子留下, 输出这些位子中最中间的那个,就是(len+1)/2 ...

随机推荐

  1. poj 3182 The Grove

    The Grove Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 641   Accepted: 297 Descripti ...

  2. [Javascript] Advanced Reduce: Common Mistakes

    Take away: Always check you ruturn the accumulator Always pass in the inital value var data = [" ...

  3. java 类加载过程

    1. 使用命令行查看类加载过程,在eclipse测试类的run configuration中配置-verbose:class或者-verbose,如下图所示: 运行结果如下所示: [Opened D: ...

  4. Visual Studio 2012 Ultimate 上安装 Python 开发插件 PTVS

    1.我的环境 操作系统:32位 Win7 旗舰版 Service Pack 1 VS版本:Microsoft Visual Studio Ultimate 2012 版本 11.0.50727.1 R ...

  5. CXF WebService整合Spring

    转自http://www.cnblogs.com/hoojo/archive/2011/03/30/1999563.html 首先,CXF和spring整合需要准备如下jar包文件: 这边我是用Spr ...

  6. Target runtime Apache Tomcat v6.0 is not defined. phyy Unknown Faceted Project Problem

    Description Resource Path Location TypeTarget runtime Apache Tomcat v6.0 is not defined. phyy Unknow ...

  7. 二叉排序树BST代码(JAVA)

        publicclassTest{     publicstaticvoid main(String[] args){         int[] r =newint[]{5,1,3,4,6,7 ...

  8. C:应用于字符串处理函数

    出于对C的不够熟悉,在读代码的过程中,平凡出现的字符串处理函数,成为了一个理解代码的大问题. 为了更方便的读取和理解代码,特意将接触到的字符串处理函数列出,方便查询: 1.strstr(str1,st ...

  9. querydsl的好处

    http://www.querydsl.com/ 封装了很多访问不同数据层平台的方法,提供统一的通用框架(统一的书写格式,以一种通用的API方式来构建查询).便于抽成统一数据层,昨晚底层,以后其他模块 ...

  10. mongodb的地理空间索引如何在solr中体现

    "$near"是唯一一个会对查询结果进行自动排序的地理空间操作符 "$near"的返回结果是按照距离由近及远排序的.其他排序条件不会生效. 这种按照地理位置远近 ...