复制代码

主席树

黑科技:静态查询第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;
 }
View Code

 

posted @ 2018-04-09 23:24  pg633  阅读(111)  评论(0编辑  收藏  举报