题意:给出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. 【面试大系】PHP程序员的知识盘点

    总结下,PHP面试中常见的知识点,以备查漏补缺和不时之用. 1)php面试题之一——PHP核心技术(高级部分)

  2. UnitOfWork以及其在ABP中的应用

    Unit Of Work(UoW)模式在企业应用架构中被广泛使用,它能够将Domain Model中对象状态的变化收集起来,并在适当的时候在同一数据库连接和事务处理上下文中一次性将对象的变更提交到数据 ...

  3. java web学习总结(十六) -------------------数据库连接池

    一.应用程序直接获取数据库连接的缺点 用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长.假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大 ...

  4. (原)3.4 Zookeeper应用 - 分布式锁

    本文为原创文章,转载请注明出处,谢谢 分布式锁 1.原理 建立表示锁的父节点(图中locker节点) 每个争抢锁的服务器在locker节点下创建有序的临时节点 判断自己是否抢到锁:获取locker下所 ...

  5. C# new关键字

    在 C# 中,new 关键字可用作运算符.修饰符或约束 1.new 运算符:用于创建对象和调用构造函数.2.new 修饰符:用作修饰符时,new 关键字可以显式隐藏从基类继承的成员.3.new 约束: ...

  6. 深入浅出node(1) Node简介

    这一系列主要是自己在学习深入浅出node.js这本书的学习笔试,部分加入了自己的一些理解 分享给一起学习node的小伙伴 自己还是个初学者 有很多地方理解的不到位 一起交流 一 什么是node 1.1 ...

  7. 委托的N种写法,你喜欢哪种?

    一.委托调用方式 1. 最原始版本: delegate string PlusStringHandle(string x, string y); class Program { static void ...

  8. iOS APP上架过程常见问题

    1.生产证书失效 2.上图中的蓝色选中部分的Provising Profile文件页需要导入,(调试证书(Developer).发布证书(distribution).还有Provising Profi ...

  9. ASP.NET获取真正的客户端IP地址的6种方法

    Request.ServerVariables("REMOTE_ADDR") 来取得客户端的IP地址,但如果客户端是使用代理服务器来访问,那取到的就是代理服务器的IP地址,而不是真 ...

  10. [css]我要用css画幅画(七) - 哆啦A梦

    接着之前的[css]我要用css画幅画(六),今天画的有所不同,画的是哆啦A梦,我们小时候对他的称呼其实是小叮当机器猫. (PS:这次我要做的事情,很多人已经做过,这并不是什么创新,我只是在学习并记录 ...