1 条题解
-
0
自动搬运
来自洛谷,原作者为

kraylas
**搬运于
2025-08-24 21:21:24,当前版本为作者最后更新于2018-09-02 20:49:02,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
貌似没有用主席树的,我就来一发主席树题解
看见楼下有用线段树的,其实主席树就是可持久的线段树 普通的线段树是对1到n的区间建树,而主席树是在1到n的区间中只插入某个前缀中的值,由于区间和具有可减性所以主席树用来解决区间第k小的问题
一开始看见题目直接就打了一个主席树板子首先树中的节点信息需要记录此区间数的数量,然后是两个儿子节点
struct pt{ int sum; pt* ch[2]; };然后建树过程因为如果每个前缀都建一棵树,那么每棵树都是O(n)的空间,总空间为彻底变为炸同学
我们发现由于每次增加一个数最多会变个节点 所以我们可以利用当前树和前一个树的公共区间来建树 总空间
typedef pt* ptr; ptr root[maxn]; int n,k; void add(ptr last,ptr& th,int v,int l=1,int r=n){ th=new pt; *th=*last; th->sum=last->sum+1; if(l==r)return ; int mid=l+r>>1; if(v<=mid)add(last->ch[0],th->ch[0],v,l,mid); else add(last->ch[1],th->ch[1],v,mid+1,r); }建树过程也完了,然后是查询,和楼下线段树dalao一样只不过区间的节点是(因为root都是前缀) 所以查询的代码也很好写
int getid(ptr le,ptr re,int k,int l=1,int r=n){ if(l==r)return l; int tmp=re->ch[0]->sum-le->ch[0]->sum; int mid=l+r>>1; if(k<=tmp)return getid(le->ch[0],re->ch[0],k,l,mid); else return getid(le->ch[1],re->ch[1],k-tmp,mid+1,r); }然后就是离散化和去重等等
完整代码:
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; const int maxn=1e5+5; struct pt{ int sum; pt* ch[2]; }; typedef pt* ptr; ptr root[maxn]; int n,k; void add(ptr last,ptr& th,int v,int l=1,int r=n){ th=new pt; *th=*last; th->sum=last->sum+1; if(l==r)return ; int mid=l+r>>1; if(v<=mid)add(last->ch[0],th->ch[0],v,l,mid); else add(last->ch[1],th->ch[1],v,mid+1,r); } int getid(ptr le,ptr re,int k,int l=1,int r=n){ if(l==r)return l; int tmp=re->ch[0]->sum-le->ch[0]->sum; int mid=l+r>>1; if(k<=tmp)return getid(le->ch[0],re->ch[0],k,l,mid); else return getid(le->ch[1],re->ch[1],k-tmp,mid+1,r); } int a[maxn]; int main(){ ptr& null=root[0]; null=new pt; null->ch[0]=null->ch[1]=null;null->sum=0; cin>>n>>k; for(int i=1;i<=n;++i){ cin>>a[i]; } sort(a+1,a+1+n); n=unique(a+1,a+1+n)-a-1; if(k>n){ cout<<"NO RESULT"<<endl; return 0; } for(int i=1;i<=n;++i){ add(root[i-1],root[i],i); } cout<<a[getid(root[0],root[n],k)]<<endl; return 0; }让我们一起%dalao
https://www.luogu.org/space/show?uid=13091
- 1
信息
- ID
- 140
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 2
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者