题意:给n个数,m次询问,每次询问L到R中第k小的数是哪个

算法1:划分树

 #include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std; const int mx=1e5+;
int tree[][mx];
int sortt[mx];
int sum[][mx]; void build(int l,int r,int c)
{
if (l==r) return ;
int m=(l+r)>>;
int isame=m-l+;
int pl=l,pr=m+;
for (int i=l;i<m;i++)
if (tree[c][i]<sortt[m]) isame--;
for (int i=l;i<=r;i++){
if (i==l) sum[c][i]=;
else sum[c][i]=sum[c][i-];
if (tree[c][i]<sortt[m]){
tree[c+][pl++]=tree[c][i];
sum[c][i]++;
}
else if ( tree[c][i]==sortt[m]&&isame){
isame--;
tree[c+][pl++]=tree[c][i];
sum[c][i]++;
}
else tree[c+][pr++]=tree[c][i];
}
build(l,m,c+);
build(m+,r,c+);
} int query(int L,int R,int l,int r,int c,int k){
if (L==R) return tree[c][L];
int s,ss;
if (l==L){
s=;
ss=sum[c][r];
}
else{
s=sum[c][l-];
ss=sum[c][r]-s;
}
int m=(L+R)>>;
if (k<=ss) return query(L,m,L+s,L+s+ss-,c+,k);
return query(m+,R,m++l-L-s,m++r-L-s-ss,c+,k-ss);
} int main(){
int n,m;
scanf("%d%d",&n,&m);
for (int i=;i<=n;i++){
scanf("%d",&sortt[i]);
tree[][i]=sortt[i];
}
sort(sortt+,sortt++n);
build(,n,);
while (m--)
{
int l,r,k;
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",query(,n,l,r,,k));
} }

算法2:主席树

 /*************************************************************
算法:主席树
思想:建n+1棵线段树,每颗线段数结构都是一样,先建一棵空树,然
后每棵树都在前一棵树的基础上进行修改。
把样例按照代码模拟一遍,就很容易理解了。
**************************************************************/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
using namespace std; const int mx=1e5+;
struct Tree ///树的节点
{
int l,r; ///树的区间
int ls,rs; ///树的左右孩子
int sum;
};
Tree tree[mx*];
int a[mx],b[mx];
int s[mx],cnt; void build(int l,int r,int &node) ///建空树,和线段树差不多
{
node=++cnt;
tree[node].l=l;
tree[node].r=r;
tree[node].sum=;
if (l==r) return ;
int m=(l+r)/;
build(l,m,tree[node].ls);
build(m+,r,tree[node].rs);
} void inser(int n1,int &n2,int pos) ///在上一棵树的基础上建立新树
{
n2=++cnt;
tree[n2].l=tree[n1].l; ///区间和上一棵树一样
tree[n2].r=tree[n1].r;
tree[n2].rs=tree[n1].rs; ///保证没有修改的部分和上一棵树一样
tree[n2].ls=tree[n1].ls;
tree[n2].sum=tree[n1].sum+;
if (tree[n1].l==tree[n1].r) return ;
int m=(tree[n1].l+tree[n1].r)/;
if (pos<=m) inser(tree[n1].ls,tree[n2].ls,pos);
else inser(tree[n1].rs,tree[n2].rs,pos);
} int query(int n1,int n2,int k) ///查询的k小的树
{
if (tree[n1].l==tree[n1].r)
{
return b[tree[n1].l];
}
int cut=tree[tree[n2].ls].sum-tree[tree[n1].ls].sum;
if (cut>=k) return query(tree[n1].ls,tree[n2].ls,k);
return query(tree[n1].rs,tree[n2].rs,k-cut);
} int main()
{
int n,m;
scanf("%d%d",&n,&m);
for (int i=;i<=n;i++)
{
scanf("%d",&a[i]);
b[i]=a[i];
}
sort(b+,n+b+);
cnt=;
build(,n,s[]);
for (int i=;i<=n;i++)
{
int pos=lower_bound(b+,b+n+,a[i])-b; ///找的a[i]要放的位置
inser(s[i-],s[i],pos);
}
while (m--)
{
int l,r,k;
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",query(s[l-],s[r],k));
}
}

poj 2104 K-th Number (划分树入门 或者 主席树入门)的更多相关文章

  1. POJ 2104:K-th Number(整体二分)

    http://poj.org/problem?id=2104 题意:给出n个数和m个询问求区间第K小. 思路:以前用主席树做过,这次学整体二分来做.整体二分在yr大佬的指点下,终于大概懂了点了.对于二 ...

  2. zoj2112 树状数组+主席树 区间动第k大

    Dynamic Rankings Time Limit: 10000MS   Memory Limit: 32768KB   64bit IO Format: %lld & %llu Subm ...

  3. 【Luogu】P3384主席树模板(主席树查询K小数)

    YEAH!我也是一个AC主席树模板的人了! 其实是个半吊子 我将尽量详细的讲出我的想法. 主席树太难,我们先搞普通线段树好了 普通线段树怎么做?我的想法是查询K次最小值,每次查完把查的数改成INF,查 ...

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

    题目传送门 可持久化线段树1(主席树) 题目背景 这是个非常经典的主席树入门题——静态区间第K小 数据已经过加强,请使用主席树.同时请注意常数优化 题目描述 如题,给定N个正整数构成的序列,将对于指定 ...

  5. 【BZOJ】1146: [CTSC2008]网络管理Network(树链剖分+线段树套平衡树+二分 / dfs序+树状数组+主席树)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1146 第一种做法(时间太感人): 第二种做法(rank5,好开心) ================ ...

  6. BZOJ_1901_Zju2112 Dynamic Rankings_树状数组+主席树

    BZOJ_1901_Zju2112 Dynamic Rankings_树状数组+主席树 题意: 给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i, ...

  7. BZOJ4012 HNOI2015开店(树链剖分+主席树)

    考虑这样一个问题:一棵树初始全是白点,有两种操作:把一个点染黑:询问某点到所有黑点的距离之和. 注意到树上两点x和y的距离为depth[x]+depth[y]-depth[lca(x,y)]*2.要求 ...

  8. LuoguP3834 【模板】可持久化线段树 1(主席树)|| 离散化

    题目:[模板]可持久化线段树 1(主席树) 不知道说啥. #include<cstdio> #include<cstring> #include<iostream> ...

  9. ZOJ 2112 Dynamic Rankings(树状数组+主席树)

    题意 \(n\) 个数,\(m\) 个操作,每次操作修改某个数,或者询问某个区间的第 \(K\) 小值. \(1 \leq n \leq 50000\) \(1 \leq m \leq 10000\) ...

随机推荐

  1. 关于Delphi中多线程传递参数的简单问题

    http://bbs.csdn.net/topics/390513469/ unit uThread; interface uses Classes; type Th = class(TThread) ...

  2. 用world写blog

    一级目录 怎么写呢? 这个和markdown那个更加方便呢? 据说插入表格有问题 我试一试         二级目录 这个大小还不错 添加第三季目录呢 三级目录 添加目录必须要用鼠标么? #inclu ...

  3. VMware中装Win2012并配置Hyper-v

    VMware中装配Win2012再配置Hyper-v,解决虚拟机监控程序已经在运行中的方法 找到虚拟机存放的位置,用记事本打开Windows Server 2012.vmx,在最后添加两行并保存: h ...

  4. RunTime的简单使用

    Runtime也就是运行时,是苹果官方提供的一套C语音库,那有什么作用呢?简单的来说,Runtime可以做很多的底层操作,比如说访问隐藏的一些成员变量,成员方法,当然包括了私有的成员变量,成员方法. ...

  5. mysql 已有数据字符集的修改

    mysql 字符集的修改 可以使用set names utf8 通过修改配置文件 可修改参数 default_character_set=utf8 但是以上修改方法只对数据库中新增的记录生效,如果数据 ...

  6. 一个C#语法高亮插件

    语法高亮对程序员阅读代码来说有着不小的帮助,虽然VisualStudio本身支持C#语法高亮,但也只是对关键字.类名.字符串等少数元素加了标记,而我们代码中主题:变量.函数.属性.事件等都没有进行高亮 ...

  7. Geometry关系高级操作

    一些高级的操作 几何形状Geometry缓冲(buffer) 线段的融合(linemerge)是将Geometry A中相互连接的线段进行连接 多边形化操作(polygonize)对Geometry ...

  8. DOM Document

    1.DOM Document对象 定义:每个载入浏览器的 HTML 文档都会成为 Document 对象.Document 对象使我们可以从脚本中对 HTML 页面中的所有元素进行访问. Docume ...

  9. 数据库一些常用的SQL语句

    1.多表连接查询: 假设现在有三个表,One,Two,Three: One表字段:Code(主键),Name Two表字段:Birthday,T_code(One表Code的外键) Three表字段: ...

  10. 循序渐进Python3(十一) --0-- web之html

    HTML: HTML是英文Hyper Text Mark-up Language(超文本标记语言)的缩写,他是一种制作万维网页面标准语言(标记). 相当于定义统一的一套规则,大家都来遵守他,这样就可以 ...