C++-LUOGU3834 可持久化线段树(主席树)[模板]

呵呵,题目都这么明确了,题解什么的,就不需要了吧!

和上一篇poj2104的题意一模一样,数据范围*2了而已,可以直接复制代码过去a掉

但是我还是兢兢业业的重新敲了一遍,种树这种事情要勤奋嘛!

介于昨天刚学,自是不能领悟Insert操作的精妙之处

故今天写代码时先建了一颗nlogn的空树,方便查找(理解)?!

其实Insert操作就可以胜任从空树到建树的全过程,实在玄妙!

附上好理解的ac代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int MAXN=2e5+10;
 4 struct Node{int l,r,sum;};
 5 struct Data{int x,id;};
 6 bool cmp(Data a,Data b){return a.x<b.x;}
 7 Node t[MAXN<<5];Data a[MAXN];
 8 int rt[MAXN],cnt,rk[MAXN];
 9 void Build(int&x,int l,int r){//建树操作要么传参要么就要记录当前节点id,cnt为全局变量不可再递归后再次使用
10     x=++cnt;if(l==r)return;
11     int mid=(l+r)>>1;
12     Build(t[x].l,l,mid);
13     Build(t[x].r,mid+1,r);
14 }
15 void Insert(int&a,int&x,int l,int r){
16     t[++cnt]=t[x],x=cnt,t[x].sum++;
17     if(l==r)return;int mid=(l+r)>>1;
18     if(a<=mid)Insert(a,t[x].l,l,mid);
19     else Insert(a,t[x].r,mid+1,r);
20 }
21 int Query(int L,int R,int k,int l,int r){
22     if(l==r)return l;int mid=(l+r)>>1;
23     int s=t[t[R].l].sum-t[t[L].l].sum;
24     if(k<=s)return Query(t[L].l,t[R].l,k,l,mid);
25     else return Query(t[L].r,t[R].r,k-s,mid+1,r);
26 }
27 int n,m,l,r,k;
28 void InputAndInit(){
29     cin>>n>>m;
30     for(int i=1;i<=n;i++)cin>>a[i].x,a[i].id=i;
31     sort(a+1,a+n+1,cmp);
32     for(int i=1;i<=n;i++)rk[a[i].id]=i;
33 }
34 int main(){
35     InputAndInit(),Build(rt[0],1,n);
36     for(int i=1;i<=n;i++)rt[i]=rt[i-1],Insert(rk[i],rt[i],1,n);
37     while(m--)cin>>l>>r>>k,cout<<a[Query(rt[l-1],rt[r],k,1,n)].x<<endl;    
38     return 0;
39 }

 

posted @ 2020-03-01 12:59  墨鳌  阅读(138)  评论(0编辑  收藏  举报