【9018:2208】可持久化線段樹2
阿新 • • 發佈:2018-03-08
body stat lin nbsp return == tro mst tdi
提交: 30 解決: 12
[提交][狀態][討論版]
2208: 【模板】可持久化線段樹2
時間限制: 3 Sec 內存限制: 256 MB提交: 30 解決: 12
[提交][狀態][討論版]
題目描述
靜態區間第K小問題是典型的主席樹模板。
在這個問題中,你需要實現對區間第K小的查詢。
輸入
第1行,輸入兩個正整數n,m,表示數列長度,查詢次數。
第2行,n個整數表示數列ai。
接下來m行,每行3個正整數l,r,k表示查詢[l,r]內的第k小數。(1<=l<=r<=n,1<=k<=r-l+1)
輸出
輸出m行,每行1個整數表示答案。
樣例輸入
5 5 25957 6405 15770 26287 26465 2 2 1 3 4 1 4 5 1 1 2 2 4 4 1
樣例輸出
6405
15770
26287
25957
26287
提示
對於100%的數據滿足:1≤N,M≤5?1051 \leq N, M \leq 2\cdot 10^5
對於數列中的所有數aia_i,均滿足?109≤ai≤109-{10}^9 \leq a_i \leq {10}^9
代碼如下:
#include<cstdio> #include<iostream> #include<algorithm> #define MN 500005 #define MM 10000005 using namespace std; int n,q,v[MN],rk[MN],vv[MN],cnt,T[MM],ls[MM],rs[MM],rt[MM];bool cmp(int x,int y){return v[x]<v[y];} void update(int &k,int l,int r,int v){ ls[++cnt]=ls[k],rs[cnt]=rs[k],k=cnt; if(l==r){T[k]=1;return;} int mid=(l+r)>>1; if(v<=mid) update(ls[k],l,mid,v); else update(rs[k],mid+1,r,v); T[k]=T[ls[k]]+T[rs[k]]; } int query(intk,int l,int r,int ql,int qr){ if(l==r) return l; int mid=(l+r)>>1; if(k<=T[ls[qr]]-T[ls[ql]]) return query(k,l,mid,ls[ql],ls[qr]); else return query(k-=T[ls[qr]]-T[ls[ql]],mid+1,r,rs[ql],rs[qr]); } int main() { scanf("%d%d",&n,&q); for(int i=1;i<=n;i++) scanf("%d",&v[i]),rk[i]=i; sort(rk+1,rk+1+n,cmp); for(int i=1;i<=n;i++) vv[rk[i]]=i; //for(int i=1;i<=n;i++) printf("%d\n",rk[i]); for(int i=1;i<=n;i++) rt[i]=rt[i-1],update(rt[i],1,n,vv[i]); for(int i=1;i<=q;i++){ int x,y,k; scanf("%d%d%d",&x,&y,&k); printf("%d\n",v[rk[query(k,1,n,rt[x-1],rt[y])]]); } return 0; }
【9018:2208】可持久化線段樹2