【模板】可持久化线段树 1(主席树)
題目背景
這是個非常經(jīng)典的主席樹入門題——靜態(tài)區(qū)間第K小
數(shù)據(jù)已經(jīng)過加強,請使用主席樹。同時請注意常數(shù)優(yōu)化
題目描述
如題,給定N個正整數(shù)構(gòu)成的序列,將對于指定的閉區(qū)間查詢其區(qū)間內(nèi)的第K小值。
輸入輸出格式
輸入格式:第一行包含兩個正整數(shù)N、M,分別表示序列的長度和查詢的個數(shù)。
第二行包含N個正整數(shù),表示這個序列各項的數(shù)字。
接下來M行每行包含三個整數(shù)l,r,k l, r, kl,r,k , 表示查詢區(qū)間[l,r][l, r][l,r]內(nèi)的第k小值。
輸出格式:輸出包含k行,每行1個正整數(shù),依次表示每一次查詢的結(jié)果
輸入輸出樣例
輸入樣例#1: 復(fù)制 5 5 25957 6405 15770 26287 26465 2 2 1 3 4 1 4 5 1 1 2 2 4 4 1 輸出樣例#1: 復(fù)制 6405 15770 26287 25957 26287說明
數(shù)據(jù)范圍:
對于20%的數(shù)據(jù)滿足:1≤N,M≤101 \leq N, M \leq 101≤N,M≤10
對于50%的數(shù)據(jù)滿足:1≤N,M≤1031 \leq N, M \leq 10^31≤N,M≤103
對于80%的數(shù)據(jù)滿足:1≤N,M≤1051 \leq N, M \leq 10^51≤N,M≤105
對于100%的數(shù)據(jù)滿足:1≤N,M≤2?1051 \leq N, M \leq 2\cdot 10^51≤N,M≤2?105
對于數(shù)列中的所有數(shù)aia_iai?,均滿足?109≤ai≤109-{10}^9 \leq a_i \leq {10}^9?109≤ai?≤109
樣例數(shù)據(jù)說明:
N=5,數(shù)列長度為5,數(shù)列從第一項開始依次為[25957,6405,15770,26287,26465][25957, 6405, 15770, 26287, 26465 ][25957,6405,15770,26287,26465]
第一次查詢?yōu)?span id="ozvdkddzhkzd" class="katex">[2,2][2, 2][2,2]區(qū)間內(nèi)的第一小值,即為6405
第二次查詢?yōu)?span id="ozvdkddzhkzd" class="katex">[3,4][3, 4][3,4]區(qū)間內(nèi)的第一小值,即為15770
第三次查詢?yōu)?span id="ozvdkddzhkzd" class="katex">[4,5][4, 5][4,5]區(qū)間內(nèi)的第一小值,即為26287
第四次查詢?yōu)?span id="ozvdkddzhkzd" class="katex">[1,2][1, 2][1,2]區(qū)間內(nèi)的第二小值,即為25957
第五次查詢?yōu)?span id="ozvdkddzhkzd" class="katex">[4,4][4, 4][4,4]區(qū)間內(nèi)的第一小值,即為26287
思路
可持久化線段樹這種東西,隨便手模不就能行了嘛;
對于每個新時段樹更新一條相關(guān)鏈,其余引用前面時段的樹枝即可;
代碼實現(xiàn)
1 #include<cstdio> 2 #include<algorithm> 3 const int maxn=2e5+10; 4 int n,m,q; 5 int s[maxn],f[maxn]={-1}; 6 int rt[maxn],rts; 7 int t[maxn<<4],ls[maxn<<4],rs[maxn<<4]; 8 void add(int q,int&p,int l,int r,int x){ 9 if(!p) p=++rts; 10 if(l==r){ 11 t[p]=t[q]+1; 12 return; 13 } 14 int mid=l+r>>1; 15 if(x<=f[mid]) rs[p]=rs[q],add(ls[q],ls[p],l,mid,x); 16 else ls[p]=ls[q],add(rs[q],rs[p],mid+1,r,x); 17 t[p]=t[ls[p]]+t[rs[p]]; 18 } 19 int see(int q,int p,int l,int r,int x){ 20 if(l==r) return f[l]; 21 int mid=l+r>>1; 22 if(x>t[ls[p]]-t[ls[q]]) return see(rs[q],rs[p],mid+1,r,x-t[ls[p]]+t[ls[q]]); 23 else return see(ls[q],ls[p],l,mid,x); 24 } 25 int main(){ 26 scanf("%d%d",&n,&q); 27 for(int i=1;i<=n;i++) scanf("%d",&s[i]),f[i]=s[i]; 28 std::sort(f+1,f+n+1); 29 for(int i=1;i<=n;i++) if(f[i]!=f[m]) f[++m]=f[i]; 30 for(int i=1;i<=n;i++) add(rt[i-1],rt[i],1,m,s[i]); 31 int l,r,k; 32 for(int i=1;i<=n;i++){ 33 scanf("%d%d%d",&l,&r,&k); 34 printf("%d\n",see(rt[l-1],rt[r],1,m,k)); 35 } 36 return 0; 37 }?
轉(zhuǎn)載于:https://www.cnblogs.com/J-william/p/8127778.html
總結(jié)
以上是生活随笔為你收集整理的【模板】可持久化线段树 1(主席树)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android中利用正则表达式验证手机号
- 下一篇: 使用 Jwt-Auth 实现 API 用