询问区间第k大 照着学长模板打的
#include<bits/stdc++.h> using namespace std; const int N=2e5+5,M=100000+5,inf=0x3f3f3f3f; int n,m,a[N],w[N]; int tl,tot=0,rt[N]; template<class t>void rd(t &x){ x=0;int w=0;char ch=0; while(!isdigit(ch)) w|=ch=='-',ch=getchar(); while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); x=w?-x:x; } struct tree{ int l,r,sum; }t[N*50]; void pup(int o){ t[o].sum=t[t[o].l].sum+t[t[o].r].sum; } void update(int l,int r,int &o,int pre,int k){ o=++tot; if(l==r){t[o].sum=t[pre].sum+1;return;} int mid=l+r>>1; if(k<=mid) update(l,mid,t[o].l,t[pre].l,k),t[o].r=t[pre].r; else update(mid+1,r,t[o].r,t[pre].r,k),t[o].l=t[pre].l; pup(o); } int query(int l,int r,int x,int y,int k){ if(l==r) return l; int mid=l+r>>1,ss=t[t[y].l].sum-t[t[x].l].sum; if(ss>=k) return query(l,mid,t[x].l,t[y].l,k); else return query(mid+1,r,t[x].r,t[y].r,k-ss); } int main(){ rd(n),rd(m); for(int i=1;i<=n;++i) rd(a[i]),w[i]=a[i]; sort(a+1,a+n+1); tl=unique(a+1,a+n+1)-a-1; for(int i=1;i<=n;++i){ w[i]=lower_bound(a+1,a+tl+1,w[i])-a; update(1,tl,rt[i],rt[i-1],w[i]); } for(int i=1,l,r,k;i<=m;++i){ rd(l),rd(r),rd(k); printf("%d ",a[query(1,tl,rt[l-1],rt[r],k)]); } return 0; }
QAQ居然和我看的那个版本不一样
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* 主席树求区间第K大模板: 模板特殊说明: 每棵树是维护从1开始到cnt的下标信息 */ #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<queue> #include<stack> #include<algorithm> #define ll long long #define go(i,x,a) for(int i=a;i<x;i++) #define INF 0x7f7f7f7f using namespace std; const int maxn=1e5+5; int T,n,m,tot,a[maxn],b[maxn],cnt,roots[maxn]; struct N { int ls, rs, w; } tree[30 * maxn]; int build_tree(int l, int r) { int newnode = tot++; tree[newnode].w = 0; if (l != r) { int mid = (l + r) / 2; tree[newnode].ls = build_tree(l, mid); tree[newnode].rs = build_tree(mid + 1, r); } return newnode; } int updata(int rt, int pos, int val) { int newnode = tot++, tmp = newnode; tree[newnode].w = tree[rt].w + val; int l = 1, r = cnt; while (l < r) { int mid = (l + r) / 2; if (pos <= mid) { tree[newnode].ls = tot++; tree[newnode].rs = tree[rt].rs; newnode = tree[newnode].ls; rt = tree[rt].ls; r = mid; } else { tree[newnode].ls = tree[rt].ls; tree[newnode].rs = tot++; newnode = tree[newnode].rs; rt = tree[rt].rs; l = mid + 1; } tree[newnode].w = tree[rt].w + val; } return tmp; } int query(int rt1, int rt2, int k) { int l = 1, r = cnt; while (l < r) { int mid = (l + r) / 2; int tmp = tree[tree[rt2].ls].w - tree[tree[rt1].ls].w; if (tmp >= k) { rt1 = tree[rt1].ls; rt2 = tree[rt2].ls; r = mid; } else { k -= tmp; rt1 = tree[rt1].rs; rt2 = tree[rt2].rs; l = mid + 1; } } return l; } int main() { scanf("%d", &T); while (T--) { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); b[i - 1] = a[i]; } sort(b, b + n); cnt = unique(b, b + n) - b; tot = 0; roots[0] = build_tree(1, cnt); for (int i = 1; i <= n; i++) { int tmp = (int)(lower_bound(b, b + cnt, a[i]) - b) + 1; roots[i] = updata(roots[i - 1], tmp, 1); } int l,r,k; for(int i=0;i<m;i++){ scanf("%d %d %d",&l,&r,&k); int tmp = query(roots[l-1],roots[r],k); printf("%d ",b[tmp - 1]); } } return 0; }//Faze