POJ2104 K-TH NUMBER 传说中的主席树
题意:给出1e5个数,向你提5000问,L到R间的第K个数是多少?
————————————————————————————————————————————————————————
这个题着实没有其它很好的办法,是主席树的经典题目。
主席树,又叫可持久化线段树或者函数式线段树。我只知道这些了,据说是一位大神没学会划分树就自己搞了这么个替代品,结果,比原来的还要强。哎~,真不知道这群大神的脑子是咋整的,膜拜吧!
本人水平有限,这是我见过的最神奇的数据结构了,感觉比伸展树、熟练剖分神奇多了,鼓捣了大半天才明白其中的原理。
说一下思路:
因为是求第k大的数,所以线段树是不行的,因为数是排好序的,所以伸展树好像也不好解决。
所以主席树用到了前缀和的思想,如果知道每个数在L前出现了几次,R前出现了几次,做差就可以在L~R间出现了几次,自然也就知道k大了!
所以,第一步把所有的数排序、去重。
数列:2 4 6 8 8 6 4 2
hash:2 4 6 8
数列变为:1 2 3 4 4 3 2 1(就是各个数在hash中的排序)
第二部建n+1个线段树,就是按照数列的顺序每读入一个数就建一个线段树,把新树在上一颗树的基础上把这个数字按照去重后的排序加入当前线段树。
这样求L~R的k值就用线段树R减去线段树L-1,在差中找k大值就可以了。



......
出现的问题:超空间
这个事大神替我们想到了,那就是每一个线段树与上一个线段树只有一条路径(根到叶)不同,所以,新树除了这条路径外所有节点都用上一个线段树的。
这样空间为第一颗线段树(4*n)+每个数字一条链(n*logn)

代码敲了1天多,主要是本人习惯于用指针和new,但是这次点太多,超时了。没办法只好给出数组模拟指针。ok!
网上有人说可以一次性malloc多个,这样可以省时通过,没来得及试,不过应该可以,但是就没有了指针+new的灵活性,不做也罢。
但是没舍得把指针的丢掉,这个理解起来清楚容易,哎~,就这麽着吧!
————————————————————————————————————————————————————————
数组版:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm> using namespace std;
const int maxn=;
const int maxnn=;
int root[maxn],ls[maxnn],rs[maxnn],cnt[maxnn],tot;
int sz[maxn],hash[maxn];
void build(int &cur,int l,int r)
{
cur=tot++;
cnt[cur]=;
if(l!=r)
{
int mid=(l+r)/;
build(ls[cur],l,mid);
build(rs[cur],mid+,r);
}
}
void update(int pre,int ps,int &cur,int l,int r)
{
cur=tot++;
cnt[cur]=cnt[pre]+;
ls[cur]=ls[pre];rs[cur]=rs[pre];
if(l==r)return ;
int mid=(l+r)/;
if(ps<=mid)update(ls[pre],ps,ls[cur],l,mid);
else update(rs[pre],ps,rs[cur],mid+,r);
}
int query(int lt,int rt,int l,int r,int k)
{
if(l==r)return l;
int mid=(l+r)/,cha=cnt[ls[rt]]-cnt[ls[lt]];
if(k<=cha)return query(ls[lt],ls[rt],l,mid,k);
else return query(rs[lt],rs[rt],mid+,r,k-cha);
}
int main()
{
int m,n,l,r,k;
while(scanf("%d%d",&n,&m)==)
{
for(int i=;i<=n;++i)
{
scanf("%d",sz+i);
hash[i]=sz[i];
}
sort(hash+,hash+n+);
int siz=unique(hash+,hash++n)-hash-;
for(int i=;i<=n;++i)
sz[i]=lower_bound(hash+,hash++siz,sz[i])-hash;
tot=;
build(root[],,siz);
for(int i=;i<=n;++i)
update(root[i-],sz[i],root[i],,siz);
while(m--)
{
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",hash[query(root[l-],root[r],,siz,k)]);
}
}
return ;
}
指针版(由于多次malloc,超时了)
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=;
struct node
{
int cnt;
node *ch[];
int l,r;
}* root[maxn];
int n,mm,l,r,k;
int sz[maxn],hash[maxn]; void readint(int &x)
{
char c=getchar();
int f=;
for(;c<''||c>'';c=getchar())if(c=='-')f=-f;
x=;
for(;c<=''&&c>='';c=getchar())x=x*+c-'';
x=x*f;
}
void build(node * &cur,int l,int r)
{
cur=(node *)malloc(sizeof(node));
cur->cnt=;
cur->ch[]=cur->ch[]=NULL;
cur->l=l;cur->r=r;
if(l!=r)
{
int mid=(l+r)/;
build(cur->ch[],l,mid);
build(cur->ch[],mid+,r);
}
}
void update(node * pre,int ps,node * &cur,int l,int r)
{
cur=(node *)malloc(sizeof(node));
cur->cnt=pre->cnt+;
cur->l=pre->l;cur->r=pre->r;
cur->ch[]=pre->ch[];
cur->ch[]=pre->ch[];
if(l==r)return ;
int mid=(l+r)/;
if(ps<=mid)update(pre->ch[],ps,cur->ch[],l,mid);
else update(pre->ch[],ps,cur->ch[],mid+,r);
}
int query(node * lt,node *rt,int l,int r,int k)
{
if(l==r)return l;
int mid=(l+r)/,cha=rt->ch[]->cnt - lt->ch[]->cnt;
if(k<=cha)return query(lt->ch[],rt->ch[],l,mid,k);
else return query(lt->ch[],rt->ch[],mid+,r,k-cha);
}
int main()
{
while(scanf("%d%d",&n,&mm)==)
{
for(int i=;i<=n;++i)
{
readint(sz[i]);
hash[i]=sz[i];
}
sort(hash+,hash+n+);
int siz=unique(hash+,hash+n+)-hash-;
for(int i=;i<=n;++i)
sz[i]=lower_bound(hash+,hash+siz+,sz[i])-hash;
build(root[],,siz);
for(int i=;i<=n;++i)
update(root[i-],sz[i],root[i],,siz);
while(mm--)
{
readint(l);readint(r);readint(k);
printf("%d\n",hash[query(root[l-],root[r],,siz,k)]);
}
}
return ;
}
POJ2104 K-TH NUMBER 传说中的主席树的更多相关文章
- [POJ2104] K – th Number (可持久化线段树 主席树)
题目背景 这是个非常经典的主席树入门题--静态区间第K小 数据已经过加强,请使用主席树.同时请注意常数优化 题目描述 如题,给定N个正整数构成的序列,将对于指定的闭区间查询其区间内的第K小值. 输入输 ...
- K-th Number Poj - 2104 主席树
K-th Number Poj - 2104 主席树 题意 给你n数字,然后有m次询问,询问一段区间内的第k小的数. 解题思路 这个题是限时训练做的题,我不会,看到这个题我开始是拒绝的,虽然题意清晰简 ...
- BZOJ_4026_dC Loves Number Theory _主席树+欧拉函数
BZOJ_4026_dC Loves Number Theory _主席树+欧拉函数 Description dC 在秒了BZOJ 上所有的数论题后,感觉萌萌哒,想出了这么一道水题,来拯救日益枯 竭 ...
- 主席树总结(经典区间第k小问题)(主席树,线段树)
接着上一篇总结--可持久化线段树来整理吧.点击进入 这两种数据结构确实有异曲同工之妙.结构是很相似的,但维护的主要内容并不相同,主席树的离散化.前缀和等思想也要更难理解一些. 闲话 话说刚学习主席树的 ...
- bzoj : 4504: K个串 区间修改主席树
4504: K个串 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 268 Solved: 110[Submit][Status][Discuss] ...
- [poj2104] K-th Number (主席树)
主席树 Description You are working for Macrohard company in data structures department. After failing y ...
- 可持久化线段树(主席树)(图文并茂详解)【poj2104】【区间第k大】
[pixiv] https://www.pixiv.net/member_illust.php?mode=medium&illust_id=63740442 向大(hei)佬(e)实力学(di ...
- POJ 2104:K-th Number(主席树静态区间k大)
题目大意:对于一个序列,每次询问区间[l,r]的第k大树. 分析: 主席树模板题 program kthtree; type point=record l,r,s:longint; end; var ...
- 主席树[可持久化线段树](hdu 2665 Kth number、SP 10628 Count on a tree、ZOJ 2112 Dynamic Rankings、codeforces 813E Army Creation、codeforces960F:Pathwalks )
在今天三黑(恶意评分刷上去的那种)两紫的智推中,突然出现了P3834 [模板]可持久化线段树 1(主席树)就突然有了不详的预感2333 果然...然后我gg了!被大佬虐了! hdu 2665 Kth ...
随机推荐
- jquery模拟LCD 时钟
查看效果网址:http://keleyi.com/keleyi/phtml/jqtexiao/24.htm 以下是HTML文件源代码: <!DOCTYPE html PUBLIC "- ...
- css3中动画(transition)和过渡(animation)详析
css3中动画(transition)和过渡(animation)详析
- View and Data API 现在支持IE11了
By Daniel Du After a long time waiting, IE11 finally supports WebGL, which enables us viewing our 3D ...
- hotCity 小程序城市选择器, 城市数据库可自己导出
hotCity 城市选择器, 城市数据库可自己导出 后台数据API 由HotApp小程序统计提供并维护,如果需要导出并部署在公司的生产环境,最后有SQL导出下载地址 开源地址 https://gith ...
- Atitit.反编译apk android源码以及防止反编译apk
Atitit.反编译apk android源码以及防止反编译apk 1.1. Tool apk逆向助手1 1.2. 二.使用dex2jar + jd-gui 得到apk的java源码1 1.3. 用 ...
- AndroidStudio配置gradle,让App自动签名
最近开发关于微信一系列功能,发现分享.支付必须要打包签名才能测试,太耽误事了,耗时耗力...在网上扒拉扒拉资料,发现有很多前辈都处理过类似问题,非常感谢大家的分享,参考链接:http://blog.c ...
- Android Studio 导入项目 出现安装Error:Cause: failed to find target with hash string 'android-23' 等错误
今天 在导入 一个新项目时 : 出现了这个错 Error:Cause: failed to find target with hash string 'android-23' in: C:\Use ...
- Android Studio 导入百度地图jar和so的正确方式
//这部分内容在百度地图的官方文档中写的比较模糊 //感觉在这种事情上浪费实际很不好,遂记录如下 //以下仅是方法之一 step1 下载sdk后解压,并把libs中的全部内容拷贝到app/libs目录 ...
- .NET 4.5 中新提供的压缩类
Windows8 的开发已经如火如荼开始了,在 Windows8 中提供的 .NET Framework 已经更新到了 4.5 版,其中又增加了一些新的特性,对压缩文件的支持就是其中之一. 在 4.5 ...
- C# Enum,Int,String的互相转换
版权声明:本文为博主原创文章,未经博主允许不得转载. Enum为枚举提供基类,其基础类型可以是除 Char 外的任何整型.如果没有显式声明基础类型,则使用Int32.编程语言通常提供语法来声明由一组已 ...