Description
Solution
将所有询问放在一起,二分答案的同时把区间[l,r]内的数按大小分类。
Code
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; struct P{int num,id;}b[100100]; bool cmp(P x,P y){return x.num<y.num;} int rk[100100],all=0; int n,m,a[100100]; struct node{int l,r,k,id; }q[50010],st[2][50010];int ans[50010]; int suml[100010],sumr[100010],_sort[100010]; void solve(int ql,int qr,int l,int r,int ansl,int ansr) { if (ql>qr) return; if (ansl==ansr) { for (int i=ql;i<=qr;i++) ans[q[i].id]=ansl; return; } int ansmid=ansl+ansr>>1,cnt=0,js0=0,js1=0; suml[l-1]=sumr[l-1]=0; for (int i=l;i<=r;i++) { suml[i]=a[i]<=ansmid;sumr[i]=a[i]>ansmid; if (a[i]<=ansmid) _sort[++cnt]=a[i]; } for (int i=l;i<=r;i++) if (a[i]>ansmid) _sort[++cnt]=a[i]; for (int i=l;i<r;i++) suml[i+1]+=suml[i],sumr[i+1]+=sumr[i]; for (int i=ql;i<=qr;i++) if (suml[q[i].r+l-1]-suml[q[i].l+l-2]>=q[i].k) { st[0][++js0]=q[i]; st[0][js0].l=suml[q[i].l+l-1]; st[0][js0].r=suml[q[i].r+l-1]; if (a[q[i].l+l-1]>ansmid) ++st[0][js0].l; } else { st[1][++js1]=q[i]; st[1][js1].l=sumr[q[i].l+l-1]; st[1][js1].r=sumr[q[i].r+l-1]; st[1][js1].k-=suml[q[i].r+l-1]-suml[q[i].l+l-2]; if (a[q[i].l+l-1]<=ansmid) ++st[1][js1].l; } for (int i=1;i<=js0;i++) q[i+ql-1]=st[0][i]; for (int i=1;i<=js1;i++) q[i+ql+js0-1]=st[1][i]; for (int i=l;i<=r;i++) a[i]=_sort[i-l+1]; solve(ql,ql+js0-1,l,l+suml[r]-1,ansl,ansmid); solve(ql+js0,qr,l+suml[r],r,ansmid+1,r); } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) { scanf("%d",&b[i].num);b[i].id=i; } sort(b+1,b+n+1,cmp); for (int i=1;i<=n;i++) { if (b[i].num!=b[i-1].num) all++,rk[all]=b[i].num; a[b[i].id]=all; } for (int i=1;i<=m;i++) { scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].k);q[i].id=i; } solve(1,m,1,n,1,n); for (int i=1;i<=m;i++) printf("%d ",rk[ans[i]]); }