C++-POJ2104-K-th Number[主席树]

主席树,大家这么叫的,也不知道为什么?

离线算法

1.先排序,离散化

2.按排名插入n个版本的线段树

3.没有修改,查询即可

由于维护的是权值的区间和,

因此只要查询版本r和l-1,做差比较即可

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 const int MAXN=100010;
 5 struct Node{int L,R,sum;};
 6 struct Data{int x,id,rank;};
 7 bool cmp(Data A,Data B){return A.x<B.x;} 
 8 int rt[MAXN],cnt,n,m;
 9 Node T[MAXN<<5];
10 Data a[MAXN];
11 void insert(int a,int&x,int L,int R) {
12     T[++cnt]=T[x],x=cnt,T[x].sum++;
13     if(L==R)return;int mid=(L+R)>>1;
14     if(a<=mid)insert(a,T[x].L,L,mid);
15     else insert(a,T[x].R,mid+1,R);
16 }
17 int query(int l,int r,int k,int L,int R){
18     if(L==R)return L;int mid=(L+R)>>1;
19     int t=T[T[r].L].sum-T[T[l].L].sum;
20     if(k<=t)return query(T[l].L,T[r].L,k,L,mid);
21     else return query(T[l].R,T[r].R,k-t,mid+1,R);
22 }
23 int main(){
24     scanf("%d%d",&n,&m);
25     for(int i=1;i<=n;i++)scanf("%d",&a[i].x),a[i].id=i;
26     sort(a+1,a+n+1,cmp);for(int i=1;i<=n;i++)a[a[i].id].rank=i;
27     for(int i=1;i<=n;i++)rt[i]=rt[i-1],insert(a[i].rank,rt[i],1,n);
28     for(int l,r,k; m--;)scanf("%d%d%d",&l,&r,&k),printf("%d\n",a[query(rt[l-1],rt[r],k,1,n)].x);
29     return 0;
30 }

猜你喜欢

转载自www.cnblogs.com/JasonCow/p/12386623.html