poj 2104 K-th Number 可持久化线段树

来源:互联网 发布:天猫美工和淘宝美工 编辑:程序博客网 时间:2024/06/05 00:55

题意:给出一排数,求区间第k小值


分析:可持久化线段树的入门题

可持久化线段树其实就是每一次进行修改操作都新建一棵线段树,而该线段树与前一棵线段树相比就只有logn个节点是不同的,所以其他节点就可以接到前一棵线段树上。

然后每一棵线段树储存的都是在当前时刻每个区间含有的元素的数量,那么我们查找区间x到y的第k小值时就相当于查找第y棵线段树-第x棵线段树的第k小值。


代码:

#include<iostream>#include<cstdio>#include<cstdlib>#include<algorithm>#define inf 0x7fffffff#define N 100005using namespace std;int n,m,tot,a[N],b[N],rank[N],root[N];struct tree{int l,r,s;}t[N*20];void build(int &d,int l,int r){d=++tot;t[d].s=0;if (l==r) return;int mid=(l+r)/2;build(t[d].l,l,mid);build(t[d].r,mid+1,r);}void insert(int &x,int y,int p,int l,int r){x=++tot;t[x].s=t[y].s+1;t[x].l=t[y].l;t[x].r=t[y].r;if (l==r) return;int mid=(l+r)/2;if (p<=mid) insert(t[x].l,t[y].l,p,l,mid);else insert(t[x].r,t[y].r,p,mid+1,r);}int query(int x,int y,int k,int l,int r){if (l==r) return l;int w=t[t[y].l].s-t[t[x].l].s,mid=(l+r)/2;if (w>=k) return query(t[x].l,t[y].l,k,l,mid);else return query(t[x].r,t[y].r,k-w,mid+1,r);}int ef(int x){int l=1,r=n,mid;while (l<=r){mid=(l+r)/2;if (x==b[mid]) return mid;if (x<b[mid]) r=mid-1;else l=mid+1;}}int main(){scanf("%d%d",&n,&m);for (int i=1;i<=n;i++){scanf("%d",&a[i]);b[i]=a[i];}sort(b+1,b+n+1);for (int i=1;i<=n;i++)rank[i]=ef(a[i]);build(root[0],1,n);for (int i=1;i<=n;i++)insert(root[i],root[i-1],rank[i],1,n);int x,y,k;while (m--){scanf("%d%d%d",&x,&y,&k);printf("%d\n",b[query(root[x-1],root[y],k,1,n)]);}}


0 0
原创粉丝点击