主席树
黑科技:静态查询第K大
首先说一下,我的理解,主席树就是持久化的线段树,因为存在规律,所以没入更新只会更新一条链,lg n
静态查询第K大 ,简单离线,然后hash ,二分 查询 然后建立 这个主席树
说一下,主席树 会有三个东西, 左,右 ,有多少元素
有几点注意:
1.qsc 的 hash 方法
2. 查询操作中的 区域和 是T[y] ---- T[x-1] ,所以你懂的
#include<bits/stdc++.h> using namespace std; #define LOACL freopen("in","r",stdin);\ freopen("out","w",stdout); #define FASTIO ios::sync_with_stdio(false); #define CLOCK cout<<1.*clock()/CLOCKS_PER_SEC<<"ms"<<"\n"; const int sz = (int)2e5 + 5; #define REP(i, a, b) for(int i=(a); i<=(b); i++) int n,m,x,y,k,a[sz],root[sz],cnt; struct tr{ int l,r,sum; }T[sz*40]; vector<int>v; int getid(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) { T[++cnt]=T[y]; T[cnt].sum++;x=cnt; if(l==r)return ; int mid =l+r>>1; if(pos<=mid) update(l,mid,T[x].l,T[y].l,pos); else update(mid+1,r,T[x].r,T[y].r,pos); } int query(int l,int r,int x,int y,int k ) { if(l==r)return l; int sum = T[T[y].l].sum - T[T[x].l].sum; int mid =l+r>>1; if(sum>=k) return query(l,mid,T[x].l,T[y].l,k); else return query(mid+1,r,T[x].r,T[y].r,k-sum); } int main() { LOACL cin>>n>>m; REP(i,1,n) { cin>>a[i]; v.push_back(a[i]); } sort(v.begin(),v.end()); v.erase(unique(v.begin(),v.end()),v.end()); REP(i,1,n) update(1,n,root[i],root[i-1],getid(a[i])); REP(i,1,m) { cin>>x>>y>>k; cout<< v[query(1,n,root[x-1],root[y],k)-1]<<endl; } return 0; }
不摸着石头过河,难道要在温柔乡睡到天昏地暗。