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; }
作为入门文章讲的很好:http://www.cnblogs.com/Rlemon/archive/2013/05/23/3094635.html