【poj 2104】K-th Number 主席树入门
2016-10-03 17:11
393 查看
给你一个序列然后m次询问,找给出区间l到r内的第k大的数。
学习主席树的第一道题,看了很多题解才略知皮毛,然后感觉黄学长的代码写的很好(最后我没怎么压行却只用了40行),就借鉴了一下(厚着脸皮说O(∩_∩)O~)。
推荐文库http://wenku.baidu.com/link?url=wJFjRpLWmXrUr03ZoVIeexFYmNIiyM2gA8MweOcbF6DZ4oAyUsv9q6keispR8OS3h7O4gPRfdP3la0dagIkxSpbDbdau74aoznqQuZBAQNm 讲的太详细,其实只要把里面的那几张图,就是手画的那个看懂了基本上就能理解了
自己总结:分析不询问区间的情况,先离散化然后建立一个权值线段树,就可以查询出哪些值出现了多少次,然后树上二分,就可以找到答案。但是问题是现在还有区间的要求,别怕依然可以用这个思想来做。在原来的想法中最重要的一点就是我们能够快速的查询出l->r比mid小的数有多少个(左子树sum),而现在不能直接这样因为有区间范围限制,但是因为没有修改操作,所以满足区间解法即l->mid中比mid小的数等于1->mid - 1->l 那么我们可以把每一个区间建立一个线段树,但是空间复杂度搞到n2,再仔细观察,我们发现其实有很多节点重复,例如1->l与1->l-1其实只有l这一条链不同,那好啊直接用之前的就可以了嘛。(在文库的那篇有图片可以帮组理解)
具体看代码
学习主席树的第一道题,看了很多题解才略知皮毛,然后感觉黄学长的代码写的很好(最后我没怎么压行却只用了40行),就借鉴了一下(厚着脸皮说O(∩_∩)O~)。
推荐文库http://wenku.baidu.com/link?url=wJFjRpLWmXrUr03ZoVIeexFYmNIiyM2gA8MweOcbF6DZ4oAyUsv9q6keispR8OS3h7O4gPRfdP3la0dagIkxSpbDbdau74aoznqQuZBAQNm 讲的太详细,其实只要把里面的那几张图,就是手画的那个看懂了基本上就能理解了
自己总结:分析不询问区间的情况,先离散化然后建立一个权值线段树,就可以查询出哪些值出现了多少次,然后树上二分,就可以找到答案。但是问题是现在还有区间的要求,别怕依然可以用这个思想来做。在原来的想法中最重要的一点就是我们能够快速的查询出l->r比mid小的数有多少个(左子树sum),而现在不能直接这样因为有区间范围限制,但是因为没有修改操作,所以满足区间解法即l->mid中比mid小的数等于1->mid - 1->l 那么我们可以把每一个区间建立一个线段树,但是空间复杂度搞到n2,再仔细观察,我们发现其实有很多节点重复,例如1->l与1->l-1其实只有l这一条链不同,那好啊直接用之前的就可以了嘛。(在文库的那篇有图片可以帮组理解)
具体看代码
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define maxn 100020 using namespace std; int n,cur[maxn],rt[80*maxn],s[80*maxn],t[maxn],m,tot,cnt,ls[maxn*80],rs[maxn*80]; int find(int x){return lower_bound(t+1,t+1+cnt,x)-t;} void inster(int l,int r,int x,int& y ,int v){ y=++tot;//因为是应用可以直接建立新的节点 s[y]=s[x]+1;//因为加入了新的数所以一定比之前的节点多一 if(l==r)return; int mid=l+r>>1; ls[y]=ls[x],rs[y]=rs[x];//还不知道是向左还是向右 管他三七二十一先赋值再说 反正后面引用会修改 if(v>mid)inster(mid+1,r,rs[x],rs[y],v);//ls[y]不变 else inster(l,mid,ls[x],ls[y],v);//rs不变 } int query(int l,int r,int x,int y,int c){////树上二分 if(l==r)return r;////找到唯一答案 int mid=l+r>>1; int k=s[ls[y]]-s[ls[x]];////和一般的线段树一模一样 if(c<=k)return query(l,mid,ls[x],ls[y],c); else return query(mid+1,r,rs[x],rs[y],c-k); } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d",cur+i),t[i]=cur[i]; sort(t+1,t+1+n); cnt=unique(t+1,t+1+n)-t-1;//离散化 for(int i=1;i<=n;i++)inster(1,cnt,rt[i-1],rt[i],find(cur[i]));//修改建树 int a,b,c; while(m--){ scanf("%d%d%d",&a,&b,&c); printf("%d\n",t[query(1,cnt,rt[a-1],rt[b],c)]);//查询答案 } return 0; }
相关文章推荐
- POJ 2104 & HDU 2665 & POJ 2761 K-th Number (主席树入门题 区间第K大)
- POJ 2104 K-th Number(主席树入门)
- poj 2104 K-th Number (划分树入门 或者 主席树入门)
- POJ 2104 K-th Number [主席树入门]【数据结构】
- 【主席树入门 && 区间内第k小的数】POJ - 2104 K-th Number
- 【POJ 2104】K-th Number 【主席树入门题】
- poj2104 k-th number 主席树入门讲解
- POJ 2104 K-th Number(分桶,线段树,主席树)
- poj2104 K-th Number 主席树
- poj 2104 区间第K小 主席树入门题
- POJ 2104(K-th Number-区间第k大-主席树)
- POJ 2104 K-th Number 主席树
- 【POJ 2104】 K-th Number 主席树模板题
- POJ2104 K-th Number 主席树
- POJ 2104(K-th Number-区间第k大-主席树)
- POJ 2104 K-th Number(主席树)
- 主席树模板 【poj2104】K-th Number
- POJ 2104 K-th Number 静态主席树(裸
- POJ 2104 K-th Number 主席树 静态区间第K大
- poj 2104 K-th Number(主席树)