可持久化线段树(主席树)
来源:互联网 发布:苏菲娜护肤品知乎 编辑:程序博客网 时间:2024/05/17 08:32
/* 可持久优化线段树 POJ2104 区间第k大值 k-th number by sbn 2017-12-21 */#include<iostream>#include<cstdio>#include<vector>#include<cstdlib>#include<algorithm>using namespace std;typedef long long ll;struct node{ int l,r; int num; //存放第i个值在原序列排第几 int sum; //线段树结点里保存的值 } tree[5000001];int n,m,tot=0,head[5000001];//每个结点在线段树中标号 int san[5000001]; //存放原有值的排序 void build(int l,int r,int &u){ u=++tot; tree[u].sum=0; if (l==r) return; build(l,(l+r)>>1,tree[u].l); build((l+r)/2+1,r,tree[u].r);}//一棵空树 void update(int last,int u,int l,int r,int &x){ // x=++tot; tree[x].l=tree[last].l; tree[x].r=tree[last].r; tree[x].sum=tree[last].sum+1; if (l==r) return; int mid=(l+r)/2; if(u<=mid) update(tree[last].l,u,l,mid,tree[x].l); else update(tree[last].r,u,mid+1,r,tree[x].r);}int query(int s,int t,int l,int r,int k){ if (l==r) return l; int mid=(l+r)/2; int cnt=tree[tree[t].l].sum-tree[tree[s].l].sum; if (k<=cnt) return query(tree[s].l,tree[t].l,l,mid,k); return query(tree[s].r,tree[t].r,mid+1,r,k-cnt);}inline void debug(){ cout<<"san:"<<endl; for (int i=1;i<=n;i++) cout<<san[i]<<" ";cout<<endl; cout<<"num:"<<endl; for (int i=1;i<=n;i++) cout<<tree[i].num<<" ";cout<<endl; cout<<"sum:"<<endl; for (int i=1;i<=n;i++) cout<<tree[i].sum<<" ";cout<<endl; cout<<"head:"<<endl; for (int i=0;i<=n;i++) cout<<head[i]<<" ";cout<<endl; cout<<"l,r"<<endl; for (int i=0;i<=n;i++) cout<<tree[head[i]].l<<","<<tree[head[i]].r<<" ";cout<<endl;}int main(){ int x,y,z; cin>>n>>m; for (int i=1;i<=n;i++) { cin>>san[i]; tree[i].num=san[i]; } sort(san+1,san+n+1); int cnt=unique(san+1,san+n+1)-san-1; //去重 cout<<cnt<<endl; build(1,cnt,head[0]); debug(); update(head[0],tree[1].num,1,cnt,head[1]); debug(); for (int i=1;i<=n;i++) tree[i].num=lower_bound(san+1,san+n+1,tree[i].num)-san; for (int i=1;i<=n;i++) update(head[i-1],tree[i].num,1,cnt,head[i]); //debug(); for (int i=1;i<=m;i++){ cin>>x>>y>>z; cout<<san[query(head[x-1],head[y],1,cnt,z)]<<endl; } return 0;}
阅读全文