HDU 2665 Kth number 可持久化线段树
来源:互联网 发布:Mac osx myeclipse 编辑:程序博客网 时间:2024/05/08 04:07
题意:给n个数和m个询问,询问l,r,k是从l~r中的第k小
思路:可持久化线段树的模板题
说下自己对可持久化线段树的理解吧
可持久化线段树的是可以保存历史版本的线段树,就是插进去第i个数的线段树的状态,这样我们可以通过state[r]-state[l-1]来得到state[l~r]
朴素做法就是维护n颗线段树,但是这样一般都会MLE
可持久化线段树利用了每次插入数只修改了线段树上一条链的特性来每次插入一个数只新建一条链来维护历史版本,空间复杂度O(n*logn+n*logn) 原树+新建的链
这样我们可以通过上述做法在得到state[l~r]
#include<stdio.h>#include<string.h>#include<iostream>#include<algorithm>#include<math.h>#include<queue>#include<stack>#include<string>#include<vector>#include<map>#include<set>using namespace std;#define lowbit(x) (x&(-x))typedef long long LL;#define maxn 100005const int inf=(1<<28)-1;struct Seg_node{ int lson,rson,sum;};int cmp(int a,int b){ return a>b;}class Segment{ public: int A[maxn],h[maxn];//原数组和hash后的数组 int Size1,Size2;//原数组和hash后的数组大小 int root[maxn];//root[i]表示第i棵树的根节点 int tot;//节点个数 Seg_node seg[maxn*20];//树的节点 void init() { tot=0; } void hash_array(int chs=0)//chs=0从小到大 { for(int i=1;i<=Size1;++i) h[i]=A[i]; if(chs) sort(h+1,h+Size1+1,cmp); else sort(h+1,h+Size1+1); Size2=1; for(int i=2;i<=Size1;++i) if(h[i]!=h[i-1]) h[++Size2]=h[i]; } void build(int l,int r,int& rt)//因为要给每个节点找左右儿子,所以& { rt=++tot; seg[rt].sum=0; if(l==r) return ; int mid=(l+r)/2; build(l,mid,seg[rt].lson); build(mid+1,r,seg[rt].rson); } void update(int last,int k,int l,int r,int& rt) { rt=++tot; seg[rt]=seg[last]; seg[rt].sum++; if(l==r) return ; int mid=(l+r)/2; if(k<=mid) update(seg[last].lson,k,l,mid,seg[rt].lson); else update(seg[last].rson,k,mid+1,r,seg[rt].rson); } int query(int rt1,int rt2,int l,int r,int k) { if(l==r) return l; int cnt=seg[seg[rt2].lson].sum-seg[seg[rt1].lson].sum; int mid=(l+r)/2; if(k<=cnt) return query(seg[rt1].lson,seg[rt2].lson,l,mid,k); else return query(seg[rt1].rson,seg[rt2].rson,mid+1,r,k-cnt); } int find(int x) { int l=1,r=Size2; while(l<=r) { int mid=(l+r)/2; if(h[mid]==x) return mid; if(h[mid]>x) r=mid-1; else l=mid+1; } return l; } void fun()//更新1~n的点的链 { init(); hash_array(); build(1,Size2,root[0]); for(int i=1;i<=Size1;++i) { int pos=find(A[i]); update(root[i-1],pos,1,Size2,root[i]); } } int Get_k(int l,int r,int k) { int tmp=query(root[l-1],root[r],1,Size2,k); return h[tmp]; }}Seg;int main(){ int T; scanf("%d",&T); while(T--) { int n,m; scanf("%d%d",&n,&m); Seg.Size1=n; for(int i=1;i<=n;++i) scanf("%d",&Seg.A[i]); Seg.fun(); for(int i=1;i<=m;++i) { int l,r,k; scanf("%d%d%d",&l,&r,&k); printf("%d\n",Seg.Get_k(l,r,k)); } } return 0;}
0 0
- hdu 2665 Kth number ( 可持久化线段树 )
- HDU 2665 Kth number 可持久化线段树
- HDU-2665 Kth number (可持久化线段树)
- HDU 2665 Kth number 可持久化线段树
- HDU 2665 Kth number [可持久化线段树 主席树]
- HDU2665 Kth number 可持久化线段树
- hdu 2665 Kth number 可持(逗)久(比)化线段树
- [POJ2104/HDU2665]Kth Number-主席树-可持久化线段树
- POJ 2104 kth number 主席树(可持久化线段树)[指针实现]
- *hdu 2665 (可持久化线段树)
- hdu 2665 Kth number(函数化线段树)
- HDU 2665 Kth number(可持续化线段树)
- hdu 4348 可持久化线段树
- hdu 5820 可持久化线段树
- hdu 2665 Kth number(线段树+归并树+二分)
- HDU 2665 Kth number 主席树,函数式线段树
- POJ 2104 K-th Number (可持久化线段树)
- [poj]-2104-K-th Number-可持久化线段树
- Nginx学习笔记1-编译Nignx,搭建开发环境
- 8. String to Integer (atoi) 字符串转为int类型的所有可能情况
- 转发:[MySQL] 实现树形的遍历(关于多级菜单栏以及多级上下部门的查询问题)
- ArcEngine在AxMapControl上绘制
- memcache 内存管理
- HDU 2665 Kth number 可持久化线段树
- 73.JAVA编程思想——JDBC
- 利用Gensim训练关于英文维基百科的Word2Vec模型(Training Word2Vec Model on English Wikipedia by Gensim)
- 74.JAVA编程思想——远程方法
- 关于多线程同步中使用的锁对象
- 百度地图-设置地图最小、最大级别
- redis 集群
- 75.JAVA编程思想——设计范式
- My Eclipse中的程序调试