模板:主席树
主席树就是可持久化线段树
求区间K大数:
#include<bits.stdc++.h> using namespace std; const int N=1e5+10; vector<int>v; struct node{ int l,r,s; }t[N*40]; int rt[N],a[N],cnt; int get(int x){return lower_bound(v.begin(),v.end(),x)-v.begin()+1;} void update(int l,int r,int x,int &y,int pos){ y=++cnt;t[y]=t[x];t[y].s++; if(l==r)return; int m=(l+r)>>1; if(pos<=m)update(l,m,t[x].l,t[y].l,pos); else update(m+1,r,t[x].r,t[y].r,pos); } int query(int l,int r,int x,int y,int num){ if(l==r)return l; int sum=t[t[y].l].s-t[t[x].l].s; int m=(l+r)>>1; if(sum>=num)return query(l,m,t[x].l,t[y].l,num); else return query(m+1,r,t[x].r,t[y].r,num-sum); } int main(){ int n,m;int x,l,r; scanf("%d%d",&n,&m); for(int i=1;i<=n;++i)scanf("%d",&a[i]),v.push_back(a[i]); sort(v.begin(),v.end());v.erase(unique(v.begin(),v.end()),v.end()); for(int i=1;i<=n;++i)update(1,n,rt[i-1],rt[i],get(a[i])); for(int i=1;i<=m;++i){ scanf("%d%d%d",&l,&r,&x); printf("%d\n",v[query(1,n,rt[l-1],rt[r],x)-1]); } return 0; }
题目描述:
你需要维护这样的一个长度为N的数组,支持如下几种操作
-
在某个历史版本上修改某一个位置上的值
-
访问某个历史版本上的某一位置的值
此外,每进行一次操作(对于操作2,即为生成一个完全一样的版本,不作任何改动),就会生成一个新的版本。版本编号即为当前操作的编号(从1开始编号,版本0表示初始状态数组)
样例输入:
5 10
59 46 14 87 41
0 2 1
0 1 1 14
0 1 1 57
0 1 1 88
4 2 4
0 2 5
0 2 4
4 2 1
2 2 2
1 1 5 91
样例输出:
59
87
41
87
88
46
代码:
#include<bits/stdc++.h> const int N=1000005; using namespace std; int a[N],n,m,q,rt[N*20]; inline int read(){ int x=0;char ch=getchar(); while(ch<'0'||ch>'9'){ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return x; } struct Persistable_Segment_Tree{ int lc[N*20],rc[N*20],val[N*20],cnt; inline void build(int &k,int l,int r){ k=++cnt; if(l==r){ val[k]=a[l]; return; } int mid=(l+r)>>1; build(lc[k],l,mid); build(rc[k],mid+1,r); } inline void ins(int &k,int pre,int l,int r,int q,int v){ k=++cnt; lc[k]=lc[pre]; rc[k]=rc[pre]; val[k]=val[pre]; if(l==r){ val[k]=v; return; } int mid=(l+r)>>1; if(q<=mid) ins(lc[k],lc[pre],l,mid,q,v); else ins(rc[k],rc[pre],mid+1,r,q,v); } inline int query(int k,int l,int r,int q){ if(l==r) return val[k]; int mid=(l+r)>>1; if(q<=mid) return query(lc[k],l,mid,q); else return query(rc[k],mid+1,r,q); } }T; int main(){ n=read(),m=read(); for(int i=1;i<=n;i++) a[i]=read(); T.build(rt[0],1,n); for(int i=1;i<=m;i++){ int pre=read(),opt=read(),x=read(); if(opt==1){ int v=read(); T.ins(rt[i],rt[pre],1,n,x,v); } if(opt==2){ printf("%d\n",T.query(rt[pre],1,n,x)); rt[i]=rt[pre]; } } }