poj 2104 K-th Number (划分树入门 或者 主席树入门)
题意:给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 (划分树入门 或者 主席树入门)的更多相关文章
- POJ 2104:K-th Number(整体二分)
http://poj.org/problem?id=2104 题意:给出n个数和m个询问求区间第K小. 思路:以前用主席树做过,这次学整体二分来做.整体二分在yr大佬的指点下,终于大概懂了点了.对于二 ...
- zoj2112 树状数组+主席树 区间动第k大
Dynamic Rankings Time Limit: 10000MS Memory Limit: 32768KB 64bit IO Format: %lld & %llu Subm ...
- 【Luogu】P3384主席树模板(主席树查询K小数)
YEAH!我也是一个AC主席树模板的人了! 其实是个半吊子 我将尽量详细的讲出我的想法. 主席树太难,我们先搞普通线段树好了 普通线段树怎么做?我的想法是查询K次最小值,每次查完把查的数改成INF,查 ...
- 洛谷P3834 [模板]可持久化线段树1(主席树) [主席树]
题目传送门 可持久化线段树1(主席树) 题目背景 这是个非常经典的主席树入门题——静态区间第K小 数据已经过加强,请使用主席树.同时请注意常数优化 题目描述 如题,给定N个正整数构成的序列,将对于指定 ...
- 【BZOJ】1146: [CTSC2008]网络管理Network(树链剖分+线段树套平衡树+二分 / dfs序+树状数组+主席树)
http://www.lydsy.com/JudgeOnline/problem.php?id=1146 第一种做法(时间太感人): 第二种做法(rank5,好开心) ================ ...
- BZOJ_1901_Zju2112 Dynamic Rankings_树状数组+主席树
BZOJ_1901_Zju2112 Dynamic Rankings_树状数组+主席树 题意: 给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i, ...
- BZOJ4012 HNOI2015开店(树链剖分+主席树)
考虑这样一个问题:一棵树初始全是白点,有两种操作:把一个点染黑:询问某点到所有黑点的距离之和. 注意到树上两点x和y的距离为depth[x]+depth[y]-depth[lca(x,y)]*2.要求 ...
- LuoguP3834 【模板】可持久化线段树 1(主席树)|| 离散化
题目:[模板]可持久化线段树 1(主席树) 不知道说啥. #include<cstdio> #include<cstring> #include<iostream> ...
- ZOJ 2112 Dynamic Rankings(树状数组+主席树)
题意 \(n\) 个数,\(m\) 个操作,每次操作修改某个数,或者询问某个区间的第 \(K\) 小值. \(1 \leq n \leq 50000\) \(1 \leq m \leq 10000\) ...
随机推荐
- Android基础开发文档汇总
一.Android 基本组件 1. Android中PackageManager使用示例 : http://blog.csdn.net/qinjuning/article/details/68678 ...
- Unity已经学会的
1.以MonoBehaviour为脚本的开发模式. 2.MonoBehaviour的大多数API. 3.动画系统大多数了解. 4.UI了解一些,能写UI. 5.Editor了解一些,能写Editor. ...
- xampp windows版本安装后无法使用大文件下载的解决办法
找到httpd.conf 在<Directory "C:/xampp/htdocs"> </Directory>添加EnableSendfile On
- C语言运算符优先级和口诀(转)
一共有十五个优先级: 1 () [] . -> 2 ! ~ -(负号) ++ -- &(取变量地址)* (type)(强制类型) sizeof 3 ...
- golang 前置补0
package main import ( "fmt" ) func main() { a := 1 fmt.Println(a) //前置补0 fmt.Printf(" ...
- 高可用Hadoop平台-Flume NG实战图解篇
1.概述 今天补充一篇关于Flume的博客,前面在讲解高可用的Hadoop平台的时候遗漏了这篇,本篇博客为大家讲述以下内容: Flume NG简述 单点Flume NG搭建.运行 高可用Flume N ...
- eclipse 建立maven项目
转自:http://www.cnblogs.com/candle806/p/3439469.html Eclipse+Maven创建webapp项目<一> 1.开启eclipse,右键ne ...
- 8天掌握EF的Code First开发系列之5 视图、存储过程和异步API
本文出自8天掌握EF的Code First开发系列,经过自己的实践整理出来. 本篇目录 视图View 存储过程 异步API 本章小结 咱们接着上一篇继续深入学习,这一篇说说Entity Framewo ...
- H5 JS API 02
1.1 网络状态 我们可以通过window. navigator.onLine来检测,用户当前的网络状况,返回一个布尔值,这个不能实时的通知. addEventListener 进行绑定online从 ...
- 提升linux下tcp服务器并发连接数限制
1.修改用户进程可打开文件数限制 在Linux平台上,无论编写客户端程序还是服务端程序,在进行高并发TCP连接处理时,最高的并发数量都要受到系统对用户单一进程同时可打开文件数量的限制(这是因为系统 ...