POJ2104 K-th Number(線段樹,二分,vector)

題意

不帶修改區間第k小。(n<=100000)ios

題解

創建線段數和vector數組(vector爲當前區間排列以後的序列)(歸併)數組

而後對於每個詢問二分答案。ide

問題就轉化爲區間有多少數小於等於二分值。ui

對於咱們每個遍歷的區間(線段數的節點)。spa

若與詢問區間不相交return0。code

若徹底包含於詢問區間則在此區間的vector上二分查找有多少數小於二分值(由於已經排好序,因此很好作)blog

如有相交部分則繼續遍歷子樹。get

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cmath>
 4 #include<iostream>
 5 #include<algorithm>
 6 #include<vector>
 7 using namespace std;  8 const int N=100010;  9 vector<int> d[N*5]; 10 struct tree{ 11     int l,r; 12 }tr[N*8]; 13 const int INF=1000000007; 14 int a[N*2]; 15 int n,m; 16 void build(int l,int r,int now){ 17     tr[now].l=l;tr[now].r=r; 18     if(l==r){ 19         d[now].push_back(-INF); 20  d[now].push_back(a[l]); 21         return; 22  } 23     int mid=(l+r)>>1; 24     build(l,mid,now*2); 25     build(mid+1,r,now*2+1); 26     int size1=d[now*2].size()-1; 27     int size2=d[now*2+1].size()-1; 28     int i=1,j=1; 29     d[now].push_back(-INF); 30     while(i<=size1&&j<=size2){ 31         if(d[now*2][i]>d[now*2+1][j])d[now].push_back(d[now*2+1][j++]); 32         else d[now].push_back(d[now*2][i++]); 33  } 34     while(i<=size1)d[now].push_back(d[now*2][i++]); 35     while(j<=size2)d[now].push_back(d[now*2+1][j++]); 36     return; 37 } 38 int getnum(int now,int K){ 39     int x=1;int y=d[now].size()-1; 40     int tmp=0; 41     while(x<=y){ 42         int mid=(x+y)>>1; 43     // cout<<x<<" "<<y<<endl;
44         if(d[now][mid]<=K){ 45             tmp=mid; 46             x=mid+1; 47  } 48         else y=mid-1; 49  } 50     return tmp; 51 } 52 int check(int l,int r,int now,int K){ 53 // cout<<l<<" "<<r<<endl;
54     if(tr[now].l>r||tr[now].r<l)return 0; 55     if(l<=tr[now].l&&tr[now].r<=r){ 56     // cout<<l<<" "<<r<<" "<<getnum(now,K)<<endl;
57         return getnum(now,K); 58  } 59     int mid=(tr[now].l+tr[now].r)>>1; 60     int tmp1=check(l,r,now*2,K); 61     int tmp2=check(l,r,now*2+1,K); 62     return tmp1+tmp2; 63 } 64 int search(int l,int r,int k){ 65     int tmp; 66     int x=-INF; 67     int y=INF; 68     while(x<=y){ 69         int mid=(x+y)>>1; 70         int num=check(l,r,1,mid); 71     // cout<<mid<<" "<<num<<endl;
72         if(num>=k){ 73             tmp=mid; 74             y=mid-1; 75  } 76         else x=mid+1; 77  } 78     return tmp; 79 } 80 int main(){ 81     scanf("%d%d",&n,&m); 82     for(int i=1;i<=n;i++){ 83         scanf("%d",&a[i]); 84  } 85     build(1,n,1); 86     for(int i=1;i<=m;i++){ 87         int l,r,k; 88         scanf("%d%d%d",&l,&r,&k); 89         int ans=search(l,r,k); 90         printf("%d\n",ans); 91  } 92     return 0; 93 }
View Code
相關文章
相關標籤/搜索