题意:给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. easyui datagrid columns field 如何支持一个或多个子属性

    //如果只需要一个子属性从value出发 {field:'customer',title:'会员手机',width:100, formatter: function(value,row,index){ ...

  2. 用OSSIM轻松分析网络设备日志

    用OSSIM轻松分析网络设备日志 基于插件的日志收集与处理模式,使得用户可以轻松的利用OSSIM来分析异构网络环境下的各种网络设备日志,下面展示一些硬件设备日志的实例,我们在RAW LOG界面里,搜索 ...

  3. tomcat日志文件定时清理备份

    以下脚本主要备份的日志文件为tomcat的catalina.out.localhost_access_log.yyyy-mm-dd.log日志和项目的日志文件,其中项目的日志文件格式为"pr ...

  4. KBMMW 4.93.10 win64 一个BUG 修正

    经常有人提到kbmmw 4.93.10 的64 位版本没有32位版本稳定. 经过官方确认,是delphi 编译器生成64 位代码内存偏移地址的错误. 在kbmMWGlobal.pas 中 有一个函数k ...

  5. IO调度算法

    简介: 当向设备写入数据块或是从设备读出数据块时,请求都被安置在一个队列中等待完成. 每个块设备都有它自己的队列. I/O调度程序负责维护这些队列的顺序,以更有效地利用介质.I/O调度程序将无序的I/ ...

  6. sublime 关闭自动更新

    第一步: 点击菜单栏“Preferences”=> "Settings-User" 进入个人参数设置页面: 第二步: 在大括号内插入如下代码:"update_che ...

  7. 基本TCP套接字编程

    1.listen函数 将主动套接字转换成一个被动套接字 backlog指定相应套接字连接队列的大小. 监听套接字有2个队列: (1)未完成连接队列,接收客户SYN,发出SYN.ACK,等待完成三次握手 ...

  8. background-position还可以这样用

    文章同步至微信公众号:http://mp.weixin.qq.com/s?__biz=MzAxMzgwNDU3Mg==&mid=401626453&idx=1&sn=6af07 ...

  9. Xrm.Utility.openEntityForm 时404.15 maxQueryString 错误 和 长度超过maxQueryStringLength值 错误

    最近的项目里用到Xrm.Utility.openEntityForm 创建新记录时分别碰到以下错误: 以及 这两个错误都是因为想传递给表单的参数太多导致的url 查询参数太长导致的,前者是因为iis的 ...

  10. C#网络编程一:C#网络编程常用特性

    特性一:委托 委托是C#语言中特有的概念,相当于C/C++中的函数指针,与C/C++中函数指针的不同之处是:委托是面向对象的.类型安全的和保险的,是引用类型.因此,对委托的使用要 "先定义. ...