主席树板子(递增序列)

mac2026-01-11  4

第k大的数

描述 你为Macrohard公司的数据结构部门工作,你的工作是重新写一个数据结构,这个数据结构能快速地找到一段数列中第k大的数。

就是说,给定一个整数数列a[1…n],其中每个元素都不相同,你的程序要能回答一组格式为Q (i , j , k)的查询,Q(i, j ,k)的意思是“在a[i…j]中第k大的数是多少?”

例如令 a = {1, 5, 2, 6, 3, 7, 4},查询格式为Q (2 , 5 , 3),数列段a[2…5] = {5, 2, 6, 3},第3大的数是5,所以答案是5。

输入 文件第一行包括一个正整数n,代表数列的总长度,还有一个数m,代表有m个查询。 n,m满足:1≤n≤100 000, 1≤m≤5 000 第二行有n个数,代表数列的元素,所有数都不相同,而且不会超过109 接下来有m行,每行三个整数i , j , k,代表一次查询, i , j , k满足1≤i≤j≤n, 1≤k≤j − i + 1

输出 输出每个查询的答案,用换行符隔开

样例输入 [复制] 7 3 1 5 2 6 3 7 4 2 5 3 4 4 1 1 7 3 样例输出 [复制] 5 6 3

#include<bits/stdc++.h> using namespace std; inline int read() { int data=0;int w=1; char ch=0; ch=getchar(); while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar(); if(ch=='-') w=-1,ch=getchar(); while(ch>='0' && ch<='9') data=(data<<3)+(data<<1)+ch-'0',ch=getchar(); return data*w; } const int N=1e5+10; int L[N<<5],R[N<<5],T[N],sum[N<<5]; int n,m,tot=0; int a[N],w[N]; inline int build(int l,int r){ int rt=++tot;sum[rt]=0; if(l<r){ int mid=(l+r)>>1; L[rt]=build(l,mid); R[rt]=build(mid+1,r); } return rt; } inline int update(int pre,int l,int r,int x){ int rt=++tot; L[rt]=L[pre],R[rt]=R[pre],sum[rt]=sum[pre]+1; if(l<r){ int mid=(l+r)>>1; if(x<=mid){ L[rt]=update(L[pre],l,mid,x); } else{ R[rt]=update(R[pre],mid+1,r,x); } } return rt; } inline int que(int prel,int prer,int l,int r,int k){ if(l>=r) return l; int mid=(l+r)>>1; int num=sum[L[prer]]-sum[L[prel]]; if(num>=k) return que(L[prel],L[prer],l,mid,k); else return que(R[prel],R[prer],mid+1,r,k-num); } int main(){ n=read();m=read(); for(int i=1;i<=n;i++){ a[i]=read();w[i]=a[i]; } sort(w+1,w+n+1); int s1=unique(w+1,w+n+1)-w-1; T[0]=build(1,s1); for(int i=1;i<=n;i++){ int x=lower_bound(w+1,w+s1+1,a[i])-w; T[i]=update(T[i-1],1,s1,x); } while(m--){ int l=read(),r=read(),k=read(); int x=que(T[l-1],T[r],1,s1,k); printf("%d\n",w[x]); } return 0; }
最新回复(0)