K-th Number
Time Limit: 20000MS   Memory Limit: 65536K
Total Submissions: 61284   Accepted: 21504
Case Time Limit: 2000MS

Description

You are working for Macrohard company in data structures department. After failing your previous task about key insertion you were asked to write a new data structure that would be able to return quickly k-th order statistics in the array segment. 
That is, given an array a[1...n] of different integer numbers, your program must answer a series of questions Q(i, j, k) in the form: "What would be the k-th number in a[i...j] segment, if this segment was sorted?" 
For example, consider the array a = (1, 5, 2, 6, 3, 7, 4). Let the question be Q(2, 5, 3). The segment a[2...5] is (5, 2, 6, 3). If we sort this segment, we get (2, 3, 5, 6), the third number is 5, and therefore the answer to the question is 5.

Input

The first line of the input file contains n --- the size of the array, and m --- the number of questions to answer (1 <= n <= 100 000, 1 <= m <= 5 000). 
The second line contains n different integer numbers not exceeding 109 by their absolute values --- the array for which the answers should be given. 
The following m lines contain question descriptions, each description consists of three numbers: i, j, and k (1 <= i <= j <= n, 1 <= k <= j - i + 1) and represents the question Q(i, j, k).

Output

For each question output the answer to it --- the k-th number in sorted a[i...j] segment.

Sample Input

7 3
1 5 2 6 3 7 4
2 5 3
4 4 1
1 7 3

Sample Output

5
6
3

Hint

This problem has huge input,so please use c-style input(scanf,printf),or you may got time limit exceed.

题解

可持久化线段树,就是动态的去开点

如果一段区间并没有被修改,那么我们就可以直接让指针指向这一段区间

如果被修改,那么我们再新建点去存它修改过后的区间

这样一来显然每次最多新建树的深度个点,也就是logn个点

然后说说基本操作

单点修改:

显然我们要修改某个点的值而不影响历史版本的线段树

那么我们就在从根节点向下找目标节点时,把路径上的点都复制一份,再在回溯时修改

最多增加logn个点

区间修改:

显然我们要修改某个区间的值而不影响历史版本的线段树

那么我们就往下走,记得pushdown和新开点

找到区间后就打标记

区间查询:

从root[now]出发,向下走,记得pushdown(pushdown的时候也要新开节点,不要忘了)

代码

//by 减维
#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<map>
#include<bitset>
#include<algorithm>
#define ll long long
#define ls l,mid
#define rs mid+1,r
using namespace std; struct number{
int val,pos;
}a[]; struct tree{
int l,r,sum;
}t[]; int n,m,cnt,ys[],root[]; bool cmp(const number&x,const number&y){return x.val<y.val;} void build(int num,int &x,int l,int r)
{
t[++cnt]=t[x];x=cnt;
++t[x].sum;
if(l==r)return ;
int mid=(l+r)>>;
if(num<=mid)build(num,t[x].l,ls);
else build(num,t[x].r,rs);
} int ask(int x,int y,int k,int l,int r)
{
if(l==r)return l;
int tt=t[t[y].l].sum-t[t[x].l].sum;
int mid=(l+r)>>;
if(k<=tt)return ask(t[x].l,t[y].l,k,ls);
else return ask(t[x].r,t[y].r,k-tt,rs);//记得一定要减去tt
} int main()
{
scanf("%d%d",&n,&m);
t[]=(tree){,,};
for(int i=;i<=n;++i)
{
scanf("%d",&a[i].val);
a[i].pos=i;
}
sort(a+,a+n+,cmp);
for(int i=;i<=n;++i)ys[a[i].pos]=i;
for(int i=;i<=n;++i)
{
root[i]=root[i-];
build(ys[i],root[i],,n);
}
for(int i=,x,y,z;i<=m;++i)
{
scanf("%d%d%d",&x,&y,&z);
printf("%d\n",a[ask(root[x-],root[y],z,,n)].val);
}
return ;
}

【可持久化线段树】POJ2104 查询区间第k小值的更多相关文章

  1. HDU 2665.Kth number-可持久化线段树(无修改区间第K小)模板 (POJ 2104.K-th Number 、洛谷 P3834 【模板】可持久化线段树 1(主席树)只是输入格式不一样,其他几乎都一样的)

    Kth number Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  2. 主席树(可持久化线段树)静态区间第K小

    传送门主席树 #include <bits/stdc++.h> #define int long long using namespace std; const int maxn=2e5+ ...

  3. hdu2665可持久化线段树,求区间第K大

    Kth number Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  4. poj 2761 主席树的应用(查询区间第k小值)

    Feed the dogs Time Limit: 6000MS   Memory Limit: 65536K Total Submissions: 22084   Accepted: 7033 De ...

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

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

  6. HDU 4417.Super Mario-可持久化线段树(无修改区间小于等于H的数的个数)

    Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  7. CF452F等差子序列 & 线段树+hash查询区间是否为回文串

    记录一下一个新学的线段树基础trick(真就小学生trick呗) 给你一个1到n的排列,你需要判断该排列内部是否存在一个3个元素的子序列(可以不连续),使得这个子序列是等差序列.\(n\) <= ...

  8. 洛谷3834 hdu2665主席树模板,动态查询区间第k小

    题目链接:https://www.luogu.com.cn/problem/P3834 对于区间查询第k小的问题,在区间数量达到5e5的时候是难以用朴素数据结构实现的,这时候主席树就应运而生了,主席树 ...

  9. 「BZOJ3065」带插入区间第K小值 替罪羊树×线段树

    题目描述 从前有\(n\)只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力\(a_i\).跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴.这时跳蚤国王决定理性愉悦一下,查询区间\(k\)小值.他 ...

随机推荐

  1. hdu2993之斜率dp+二分查找

    MAX Average Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  2. SAP ABAP编程 Table Control动态隐藏列

    在SAP DIALOG设计中,有时候须要动态的隐藏某些列,以下是方法. ***数据定义 CONTROLS: table_control TYPE TABLEVIEW USING SCREEN 0100 ...

  3. gcc 源代码分析-前端篇3

    3. GCC怎样函表示一个函数   对c语言来说.函数是其核心,全部的东西都在环绕着函数在转.对于一个函数来说.它基本的一些特性例如以下:    1. 有一个返回值,在这里我们没有把返回值的函数觉得它 ...

  4. 为什么要使用消息认证码(MAC)而非对称密钥?

    问题: 看了消息认证码的介绍后,小丽心想"如果用对称密码将消息加密后再发送的话,是不是就不需要消息认证码了呢?"原因有下: 1.对称密码的密文只有使用和加密时相同的密钥才能正确解密 ...

  5. Intellij idea 复制粘贴查找快捷键失效

    遇到此问题,竟不能复制, 发现原因,是因为勾选了Vim模式, Tools,Vim Emulator,前面会有一个√,取消即可,如图: 我的是这个原因,复制粘贴快捷键失效,也有可能历史粘贴板的深度不够 ...

  6. 深入分析JavaWeb技术内幕(修订版)》【PDF】下载

    <深入分析JavaWeb技术内幕(修订版)>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230062569 内容简介 <深入分析 ...

  7. 合并查询结果集UNION(去重), UNION ALL(不去重),INTERSECT(交集),MINUS(差集,第一个结果集减去第二个结果集,第一个结果集中不在第二个结果集中的记录行),[NOT] EXIST

    MINUS配合[NOT] EXIST使用可以查询出包含符合某个条件的多记录的其他记录, 举例: 顾客A买了商品2.4.6 顾客B买了商品1.2.4 顾客C买了商品4.6 顾客D买了商品1.2.4.6 ...

  8. ed命令

  9. CSS文字不换行,溢出省略

    white-space:nowrap; overflow:hidden; text-overflow:ellipsis;

  10. 推荐:让你快速搞定各服务端(api,pc,mobile,wechat)代码

    如果你在写服务端 (PHP) ,会因为项目须求(做app.pc.mobiel.微信) 而写几套代码的,你不觉得很累吗? 现在的很多开源框架商用版本在做程序方面都是这么一套一套的,维护起来,二开起来特别 ...