Poj 2104(主席树入门

题目:静态查询区间第k大.

主席树入门题目,之前看的很多资料一上来就是动态区间第k大,看得很费劲,后来找了个写得清晰的,感觉静态的还不算难,代码也不长.

/*
* @author:  Cwind
*/
//#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <queue>
#include <stack>
#include <functional>
#include <set>
#include <cmath>
using namespace std;
#define IOS std::ios::sync_with_stdio (false);std::cin.tie(0)
#define pb push_back
#define PB pop_back
#define bk back()
#define fs first
#define se second
#define sq(x) (x)*(x)
#define eps (1e-6)
#define IINF (1<<29)
#define LINF (1ll<<59)
#define INF (1000000000)
#define FINF (1e3)
#define clr(x) memset((x),0,sizeof (x));
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> P;

const int maxn=3e6;
const int maxlen=1e5+300;
struct Node{
    int ls,rs,v;
    Node():ls(0),rs(0),v(0){}
}T[maxn];
int sz=0;
int d[maxlen],a[maxlen];
void insert(int &n,int l,int r,int x){
    T[++sz]=T[n];n=sz;
    T[n].v++;
    if(r-l<=1) return;
    int m=(r+l)>>1;
    if(x>=d[m]) insert(T[n].rs,m,r,x);
    else insert(T[n].ls,l,m,x);
}
int query(int i,int j,int l,int r,int k){
    if(r-l<=1) return d[l];
    int t=T[T[j].ls].v-T[T[i].ls].v;
    int m=(l+r)>>1;
    if(t>=k) return query(T[i].ls,T[j].ls,l,m,k);
    else return query(T[i].rs,T[j].rs,m,r,k-t);
}
int n,m;
int root[maxlen];
int main(){
    freopen("/home/files/CppFiles/in","r",stdin);
    cin>>n>>m;
    for(int i=0;i<n;i++){
        scanf("%d",&a[i]);
        d[i]=a[i];
    }
    sort(d,d+n);
    for(int i=0;i<n;i++){
        root[i+1]=root[i];
        insert(root[i+1],0,n,a[i]);
    }
       while(m--){
           int x,y,z;
           scanf("%d%d%d",&x,&y,&z);
           printf("%d\n",query(root[x-1],root[y],0,n,z));
       }
    return 0;
}
View Code

作为入门文章讲的很好:http://www.cnblogs.com/Rlemon/archive/2013/05/23/3094635.html

posted @ 2015-10-04 20:42  PlusSeven  阅读(140)  评论(0编辑  收藏  举报