题意:给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. jquery ajax 返回值 中文时乱码或变成问号解决方法

    转载自jquery的 ajax返回值为中文时乱码解决方法 用jquery的ajax,遇到个问题,服务器端从数据库取到的数据没有出现中文乱码问题(日志打出来是没有乱码的),但是异步传到客户的时候却出现了 ...

  2. 解决sublime text3 文件名,小框框的办法

    解决sublime text3 文件名,小框框的办法 之前一直都是用的英文命名的文件夹,到前几天才发现,用中文,来命名文件夹出现了乱码问题. 今天晚上,自己也在网上去百度了很多方案,好像大部分都不太有 ...

  3. HTML5移动端图片上传模块

    上传图片的功能是极为常用的,之前做过一个移动端上传文件的功能(基于jquery的),总结梳理一下. html <div class="uploadPic clearBox"& ...

  4. Python交互式编程导论----事件驱动编程

    传统的编程是如下线性模式的: 开始--->代码块A--->代码块B--->代码块C--->代码块D--->......--->结束 每一个代码块里是完成各种各样事情 ...

  5. vim显示行号、语法高亮、自动缩进的设置

    转载自:http://blog.csdn.net/chuanj1985/article/details/6873830   在UBUNTU中vim的配置文件存放在/etc/vim目录中,配置文件名为v ...

  6. 《CoffeeScript应用开发》学习:第三章-构建简单的应用程序

    字符串插值 CoffeeScript提供了一种更好的构建字符串的解决方案.在双引号字符串(单引号无效)中使用#{}包含一个动态的值. str = 'Hello, CoffeeScript.' cons ...

  7. Xslt 1.0中使用Array

    XSLT Variable Arrays I recently answered a question on a popular programmers forum about how to stor ...

  8. SQL Server中Rowcount与@@Rowcount的用法

    rowcount的用法: rowcount的作用就是用来限定后面的sql在返回指定的行数之后便停止处理,比如下面的示例, set rowcount 10select * from 表A 这样的查询只会 ...

  9. 关于VS快捷键的使用总结

    首先快捷键是为了快,不能为了用快捷键而用快捷键. 既然说到快,我个人认为要涉及到一个使用频率问题,如果一个功能的快捷键使用频率极高,那么就应该把它调到触手可及的位置, 如:经常看别人源代码,经常会使用 ...

  10. Jquery--动画

    动画: 1.show(),hide() 2..stop() .slideDown();  向下. .stop().slideUp();  向上 (可以做下拉)        .stop() 执行之前加 ...