I have been doing this for the past few days. Today I have finally understood it. The functional Line Segment tree is a data structure that solves offline algorithms. I understand it in this way. It discretization all data, another idea is to create a line segment tree (1, N) for each node N. Of course, if so many line segment trees are actually built, the memory will definitely burst, so this is the advanced part of the functional Line Segment tree. It uses the prefix and idea, and the next tree shares half of the node with the previous one. What does it mean, if we get t [N], that is, (1, N) Line Segment trees of these nodes, we need to create (1, n + 1) this line segment tree T [n + 1], so we only need to add the node A [n + 1] on the basis of T [N, if a [n + 1] is placed in the left subtree of T [n + 1], t [n + 1] will share the right subtree with T [N]. Similarly, if a [n + 1] is placed in the right subtree, t [n + 1] shares the left subtree with T [N], which can reduce the consumption of too much memory. After this tree is built, we can use its nature to solve some problems, especially the k-th large number in the interval, which can be used to handle both dynamic and static problems, for static queries (L, R, k), you only need to look at the difference between the left subtree of R and the left subtree of the L-1, if more than K, continue to search for the k-th percentile from their left subtree. If it is smaller than K, search for K-their variance from their right subtree until it reaches the leaf node, that is what we want. For dynamic, we can use a tree array to set up this functional Line Segment tree, that is, each node of the tree array is a line segment tree. In this way, a static program is provided below.
Poj 2104
#include<map>#include<set>#include<stack>#include<queue>#include<cmath>#include<vector>#include<cstdio>#include<string>#include<cstring>#include<cstdlib>#include<iostream>#include<algorithm>#define inf 0x0f0f0f0fusing namespace std;const double pi=acos(-1.0);const double eps=1e-8;typedef pair<int,int>pii;const int maxn=200000+10;const int N=maxn*30;int a[maxn],b[maxn],Ls[N],Rs[N],T[maxn],sum[N],n,m,tot;void init(){ sort(b+1,b+n+1); m=unique(b+1,b+n+1)-b-1; for (int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+m+1,a[i])-b;}int build(int x,int y){ int root=tot++; sum[root]=0; if (x==y) return root; int mid=x+(y-x)/2; Ls[root]=build(x,mid); Rs[root]=build(mid+1,y);}int insert(int root,int x,int v){ int newroot=tot++,temp=newroot; sum[newroot]=sum[root]+v; int L=1,R=m; while(L<R) { int mid=L+(R-L)/2; if (x<=mid) { Ls[newroot]=tot++; Rs[newroot]=Rs[root]; newroot=Ls[newroot]; root=Ls[root]; R=mid; } else { Ls[newroot]=Ls[root]; Rs[newroot]=tot++; newroot=Rs[newroot]; root=Rs[root]; L=mid+1; } sum[newroot]=sum[root]+v; } return temp;}int get_K_num(int Lroot,int Rroot,int k){ int L=1,R=m; while(L<R) { int mid=L+(R-L)/2; int t=sum[Ls[Rroot]]-sum[Ls[Lroot]]; if (t>=k) { R=mid; Rroot=Ls[Rroot]; Lroot=Ls[Lroot]; } else { L=mid+1; Rroot=Rs[Rroot]; Lroot=Rs[Lroot]; k-=t; } } return L;}int main(){ int q,x,y,k; while(scanf("%d%d",&n,&q)!=EOF) { tot=0; for (int i=1;i<=n;i++) { scanf("%d",&a[i]); b[i]=a[i]; } init(); T[0]=build(1,m); for (int i=1;i<=n;i++) T[i]=insert(T[i-1],a[i],1); while(q--) { scanf("%d%d%d",&x,&y,&k); printf("%d\n",b[get_K_num(T[x-1],T[y],k)]); } } return 0;}
Author: chensunrise