标签:ack color 排列 pre 遍历 alt algo scanf print
不带修改区间第k小。(n<=100000)
建立线段数和vector数组(vector为当前区间排列之后的序列)(归并)
然后对于每一个询问二分答案。
问题就转化为区间有多少数小于等于二分值。
对于我们每一个遍历的区间(线段数的节点)。
若与询问区间不相交return0。
若完全包含于询问区间则在此区间的vector上二分查找有多少数小于二分值(因为已经排好序,所以很好做)
若有相交部分则继续遍历子树。
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 }
POJ2104 K-th Number(线段树,二分,vector)
标签:ack color 排列 pre 遍历 alt algo scanf print
原文地址:https://www.cnblogs.com/Xu-daxia/p/9392549.html