题目链接

主席树=可持久化权值线段树。

如果你不会可持久化线段树,请右转

如果你不会权值线段树,请自行脑补,就是线段树维护值域里有多少个数出现。

可持久化线段树是支持查询历史版本的。

我们对每个数都进行一次基于上个版本的单点修改操作,这样每个版本就是维护的前\(p\)个数,这个权值显然满足可减性。

所以,要查询区间\([l,r]\)的第\(k\)大时,我们就用第\(r\)个版本减去第\(l-1\)个版本,我们就得到了一颗\([l,r]\)的权值线段树,然后跑第\(k\)小就简单了:

如果左儿子有大于等于\(k\)个数,就继续去左儿子找第\(k\)小,否则设左儿子的值为\(lcnt\),去右儿子找第\(k-lcnt\)小。

#include <cstdio>
#include <algorithm>
using std::sort;
#define re register
inline int read(){
int s = 0, w = 1;
char ch = getchar();
while(ch < '0' || ch > '9') { if(ch == '-') w = -1; ch = getchar(); }
while(ch >= '0' && ch <= '9') { s = s * 10 + ch - '0'; ch = getchar(); }
return s * w;
}
const int MAXN = 200010;
const int MAXM = 200010;
const int MAXMLOGN = 4000010;
struct SegTree{
int lc, rc, cnt;
SegTree(){ lc = rc = cnt = 0; }
}t[MAXMLOGN];
int root[MAXM];
int a[MAXN], c[MAXN], d[MAXN];
int n, m, tot, num;
int build(int l, int r){
int id = ++tot;
if(l == r) return id;
int mid = (l + r) >> 1;
t[id].lc = build(l, mid);
t[id].rc = build(mid + 1, r);
return id;
}
int insert(int now, int l, int r, int x){
int id = ++tot;
t[id] = t[now];
if(l == r){ ++t[id].cnt; return id; }
int mid = (l + r) >> 1;
if(x <= mid) t[id].lc = insert(t[now].lc, l, mid, x);
else t[id].rc = insert(t[now].rc, mid + 1, r, x);
t[id].cnt = t[t[id].lc].cnt + t[t[id].rc].cnt;
return id;
}
int ask(int p, int q, int l, int r, int k){
if(l == r) return l;
int mid = (l + r) >> 1;
int L = t[t[p].lc].cnt - t[t[q].lc].cnt;
if(k <= L) return ask(t[p].lc, t[q].lc, l, mid, k);
else return ask(t[p].rc, t[q].rc, mid + 1, r, k - L);
}
struct divide{
int id, val;
bool operator < (const divide A) const{
return val < A.val;
}
}b[MAXN];
int l, r, k;
int main(){
n = read(); m = read();
for(re int i = 1; i <= n; ++i){
b[i].val = a[i] = read();
b[i].id = i;
}
sort(b + 1, b + n + 1);
b[0].val = -2147483646;
for(int i = 1; i <= n; ++i)
if(b[i].val != b[i - 1].val){
c[b[i].id] = ++num;
d[num] = b[i].val;
}
else c[b[i].id] = num;
root[0] = build(1, num);
for(int i = 1; i <= n; ++i)
root[i] = insert(root[i - 1], 1, num, c[i]);
for(re int i = 1; i <= m; ++i){
l = read(); r = read(); k = read();
printf("%d\n", d[ask(root[r], root[l - 1], 1, num, k)]);
}
getchar();
return 0;
}

【洛谷 P3834】 可持久化线段树1(主席树)的更多相关文章

  1. 洛谷P3834 可持久化线段树(主席树)模板

    题目:https://www.luogu.org/problemnew/show/P3834 无法忍受了,我要写主席树! 解决区间第 k 大查询问题,可以用主席树,像前缀和一样建立 n 棵前缀区间的权 ...

  2. 洛谷 [P3834] 可持久化线段树(主席树)

    主席树可以存储线段树的历史状态,空间消耗很大,一般开45n即可 #include <iostream> #include <cstdio> #include <cstri ...

  3. 洛谷 P3919 可持久化线段树 题解

    题面 这题好水的说~很明显就是主席树的大板子 然而我交了3遍才调完所有的BUG,开好足够的数组,卡掉大大的常数: 针对与每次操作,change()会创建新节点,而ask()虽然也会更新左右儿子的节点编 ...

  4. 洛谷P2633 Count on a tree(主席树,倍增LCA)

    洛谷题目传送门 题目大意 就是给你一棵树,每个点都有点权,每次任意询问两点间路径上点权第k小的值(强制在线). 思路分析 第k小......又是主席树了.但这次变成树了,无法直接维护前缀和. 又是树上 ...

  5. 洛谷P2633 Count on a tree(主席树,倍增LCA,树上差分)

    洛谷题目传送门 题目大意 就是给你一棵树,每个点都有点权,每次任意询问两点间路径上点权第k小的值(强制在线). 思路分析 第k小......又是主席树了.但这次变成树了,无法直接维护前缀和. 又是树上 ...

  6. 2018.07.01洛谷P2617 Dynamic Rankings(带修主席树)

    P2617 Dynamic Rankings 题目描述 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i ...

  7. 【洛谷4587】 [FJOI2016]神秘数(主席树)

    传送门 BZOJ 然而是权限题 洛谷 Solution 发现题目给出的一些规律,emm,如果我们新凑出来的一个数,那么后面一个数一定是\(sum+1\). 于是就可以主席树随便维护了! 代码实现 #i ...

  8. 洛谷P2633/bzoj2588 Count on a tree (主席树)

    洛谷P2633/bzoj2588 Count on a tree 题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K ...

  9. 【洛谷 P3168】 [CQOI2015]任务查询系统(主席树)

    题目链接 被自己的sb错误调到自闭.. 主席树的进阶应用. 把\(P_i\)离散化一下,得到每个\(P_i\)的排名,然后建一棵维护\(m\)个位置的主席树,每个结点记录区间总和和正在进行的任务数. ...

  10. 【洛谷 P3899】 [湖南集训]谈笑风生 (主席树)

    题目链接 容易发现\(a,b,c\)肯定是在一条直链上的. 定义\(size(u)\)表示以\(u\)为根的子树大小(不包括\(u\)) 分两种情况, 1.\(b\)是\(a\)的祖先,对答案的贡献是 ...

随机推荐

  1. iOS开发中常见的一些异常

    iOS开发中常见的异常包括以下几种NSInvalidArgumentExceptionNSRangeExceptionNSGenericExceptionNSInternallnconsistency ...

  2. EFT4 生成实体类

    创建T4模本拷贝以下代码 <#@ template language="C#" debug="false" hostspecific="true ...

  3. MySQL☞insert value与values

    最近公司事情太忙,作为以一挑十的测试,只能苦逼的累死累活的.好不容易临近上线,可以偷个懒写个文章. 简单的说说如何向表中插入数据: 1.向表中所有的列插入数据(插入多行数据): insert  int ...

  4. C语言关于“输入包含多行数据,请处理到文件结束”的问题

    今天,笔者在做本校ACM校赛网络赛的时候,遇到输入格式中有这样的要求:输入包含多行数据,请处理到文件结束.题目的逻辑很简单,主要功能代码很容易实现,但是题目中没有“明确”指出控制台中输入数据以什么方式 ...

  5. C++ 学习笔记之——文件操作和文件流

    1. 文件的概念 对于用户来说,常用到的文件有两大类:程序文件和数据文件.而根据文件中数据的组织方式,则可以将文件分为 ASCII 文件和二进制文件. ASCII 文件,又称字符文件或者文本文件,它的 ...

  6. mysql分布式技术

    所有的分布式技术 dobble zokkiper ngix

  7. windows下git hub的GUI软件配置与使用

    转载自:http://www.cnblogs.com/haore147/p/3618930.html   1. 安装两个软件 1 2 1. git的命令行程序--git for windows:htt ...

  8. POJ 1703 Find them, Catch them(并查集拓展)

    Description The police office in Tadu City decides to say ends to the chaos, as launch actions to ro ...

  9. ACM训练大纲

    1. 算法总结及推荐题目 1.1 C++ STL • STL容器: set, map, vector, priority_queue, queue, stack, deque, bitset• STL ...

  10. 线段树——hdu1166敌兵布阵

    一.题目回顾 题目链接:敌兵布阵 Problem Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个 ...