[转载]一篇还算可以的文章,关于可持久化线段树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. [Redux] Avoiding Array Mutations with concat(), slice(), and ...spread

    For Redux, you cannot use mutable methods like push, splice. Need to use immutable methods such as c ...

  2. 如何完全退出android应用程序

    当一个android应用程序包含多个activity时,要完全退出android应用程序,便要销毁掉所有的activity,下面是一种网上流传的比较经典完美的方法: 首先要定义一个继承Applicat ...

  3. 数据库 SQL 外键约束 多表查询

    多表设计与多表查询 1.外键约束        表是用来保存现实生活中的数据的,而现实生活中数据和数据之间往往具有一定的关系,我们在使用表来存储数据时,可以明确的声明表和表之前的依赖关系,命令数据库来 ...

  4. C#Linq的使用

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  5. 为什么不使用frame框架的原因

    框架的优点 重载页面时不需要重载整个页面,只需要重载页面中的一个框架页(减少了数据的传输,增加了网页下载速度) 方便制作导航栏 框架的缺点 会产生很多页面,不容易管理 不容易打印 浏览器的后退按钮无效 ...

  6. Nopcommerce商城添加【满XX减XX优惠券】功能

    公司的电商网站要做个优惠券的功能,nop框架,但我接触nop时间不多,最后还是为了功能而完成了.这中间肯定有很多小问题. Nopcommerce自带的促销功能感觉不是很好,首先优惠券功能放在购物车页面 ...

  7. AJAX校验用户名是否存在,焦点离开用户名、点击 【 检 查用户名 】的校验。分别用 XMLHttp 和 JQueryAJAX实现。

     XMLHttp方法: $("#name").blur(function () { var xmlhttp = new ActiveXObject("Microsoft. ...

  8. android 检查网络是否可用,如果不可用弹出设置,让用户改变

    /** * 校验网络,如果没有网络,返回true * * @return boolean */ @Override public boolean hasInternetConnected() { Co ...

  9. 将图片转换为Base64

    string Imagefilename   硬盘路径 protected string ImgToBase64String(string Imagefilename) { try { Bitmap ...

  10. 1.1 语言与平台 [Java]

    Java语言是静态类型.面向对象的语言: Java平台是提供运行时环境的软件: 生产和使用Java代码的整个过程:.java (javac) .class (类加载器) 转换后的.class (解释器 ...