题意:给出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 传说中的主席树的更多相关文章

  1. [POJ2104] K – th Number (可持久化线段树 主席树)

    题目背景 这是个非常经典的主席树入门题--静态区间第K小 数据已经过加强,请使用主席树.同时请注意常数优化 题目描述 如题,给定N个正整数构成的序列,将对于指定的闭区间查询其区间内的第K小值. 输入输 ...

  2. K-th Number Poj - 2104 主席树

    K-th Number Poj - 2104 主席树 题意 给你n数字,然后有m次询问,询问一段区间内的第k小的数. 解题思路 这个题是限时训练做的题,我不会,看到这个题我开始是拒绝的,虽然题意清晰简 ...

  3. BZOJ_4026_dC Loves Number Theory _主席树+欧拉函数

    BZOJ_4026_dC Loves Number Theory _主席树+欧拉函数 Description  dC 在秒了BZOJ 上所有的数论题后,感觉萌萌哒,想出了这么一道水题,来拯救日益枯 竭 ...

  4. 主席树总结(经典区间第k小问题)(主席树,线段树)

    接着上一篇总结--可持久化线段树来整理吧.点击进入 这两种数据结构确实有异曲同工之妙.结构是很相似的,但维护的主要内容并不相同,主席树的离散化.前缀和等思想也要更难理解一些. 闲话 话说刚学习主席树的 ...

  5. bzoj : 4504: K个串 区间修改主席树

    4504: K个串 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 268  Solved: 110[Submit][Status][Discuss] ...

  6. [poj2104] K-th Number (主席树)

    主席树 Description You are working for Macrohard company in data structures department. After failing y ...

  7. 可持久化线段树(主席树)(图文并茂详解)【poj2104】【区间第k大】

    [pixiv] https://www.pixiv.net/member_illust.php?mode=medium&illust_id=63740442 向大(hei)佬(e)实力学(di ...

  8. POJ 2104:K-th Number(主席树静态区间k大)

    题目大意:对于一个序列,每次询问区间[l,r]的第k大树. 分析: 主席树模板题 program kthtree; type point=record l,r,s:longint; end; var ...

  9. 主席树[可持久化线段树](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 ...

随机推荐

  1. 更新整理本人所有博文中提供的代码与工具(Java,2014.01)

    为了更方便地管理博文中涉及的各种代码与工具资源,现在把这些资源迁移到 Google Code 中,有兴趣者可前往下载. Java 1.<高效 Java Web 应用开发框架 JessMA v3. ...

  2. 浅谈C# 多态的法力

    前言:我们都知道面向对象的三大特性:封装,继承,多态.封装和继承对于初学者而言比较好理解,但要理解多态,尤其是深入理解,初学者往往存在有很多困惑,为什么这样就可以?有时候感觉很不可思议,由此,面向对象 ...

  3. jQuery DateTimePicker 日期控件

    在线实例 实例演示 使用方法 <input id="datetimepicker" type="text" > 复制 $('#datetimepic ...

  4. CSS 优先级判断

    在面试中被问到这个问题 来记录下  发现自己之前之所以会忘记还是缺少理解的记忆 参考 CSS权威指南 一个CSS选择器的特殊性值表述为4个部分  0 0 0 0 对于选择器中给定的各个ID的属性值   ...

  5. CSS的一些基础知识

    <!DOCTYPE html><html><head><meta charset="utf-8"><title>标题&l ...

  6. JAVA简单工厂模式(从现实生活角度理解代码原理)

    简单工厂模式(Simple Factory),说他简单是因为我们可以将此模式比作一个简单的民间作坊,他们只有固定的生产线生产固定的产品.也可以称他为静态工厂设计模式,类似于之前提到过静态代理设计模式, ...

  7. Android Studio导入修改

  8. com.sun.xml.internal.ws.server.ServerRtException: Server Runtime Error: java.net.BindException: Cannot assign requested address: bind

    在发布 web service 时报错: Endpoint.publish(publishAddress, hl7MessageReveiver); com.sun.xml.internal.ws.s ...

  9. Python单例模式

    1.单例模式介绍 单例模式,也叫单子模式,是一种常用的软件设计模式.在应用这个模式时, 单例对象的类必须保证只有一个实例存在.许多时候整个系统只需要拥有一个 全局对象,这样有利于我们协调系统整体的行为 ...

  10. wubi安装ubuntukylin-14.04

    自ubuntukylin-14.04发布以来一直想体验一下,正好五一休假有了时间,在经历了一番坎坷后终于安装成功.安装环境为Win7家庭高级版,至于采用wubi方式安装,只因Linux水平差和图省事, ...