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 }
~~Jason_liu O(∩_∩)O