模板—算法—整体二分(区间k小值)
模板—算法—整体二分(区间k小值)
Code:
#include <cstdio> #include <algorithm> using namespace std; #define N 200010 int num[N],number[N],tmp[N],ans[N],n,m,id[N]; struct Ask {int l,r,id,k;}ask[N],ask1[N],ask2[N]; void change(int x,int y) {while(x<=n) tmp[x]+=y,x+=x&-x;} int find(int x) {int sum=0;while(x) sum+=tmp[x],x-=x&-x;return sum;} bool cmp(const int &a,const int &b) {return num[a]<num[b];} int find_ord(int x) { int l=1,r=n+1; while(l<r) { int mid=(l+r)>>1; if(number[mid]>=x) r=mid; else l=mid+1; } return l; } void solve(int l,int r,int tl,int tr) { if(l==r) {for(int i=tl;i<=tr;i++) ans[ask[i].id]=number[l]/*,printf("%d %d\n",ask[i].id,l)*/;return;} for(int i=l;i<=(l+r)>>1;i++) change(id[i],1); int top1=0,top2=0; for(int i=tl;i<=tr;i++) if(find(ask[i].r)-find(ask[i].l-1)>=ask[i].k) ask1[++top1]=ask[i]; else ask2[++top2]=ask[i],ask2[top2].k-=find(ask[i].r)-find(ask[i].l-1); for(int i=1;i<=top1;i++) ask[tl+i-1]=ask1[i]; for(int i=1;i<=top2;i++) ask[tl+top1+i-1]=ask2[i]; for(int i=l;i<=(l+r)>>1;i++) change(id[i],-1); solve(l,(l+r)>>1,tl,tl+top1-1),solve(((l+r)>>1)+1,r,tl+top1,tr); } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&num[i]),number[i]=num[i],id[i]=i; sort(number+1,number+n+1),sort(id+1,id+n+1,cmp); for(int i=1;i<=n;i++) num[i]=find(num[i]); for(int i=1;i<=m;i++) scanf("%d%d%d",&ask[i].l,&ask[i].r,&ask[i].k),ask[i].id=i; solve(1,n,1,m); for(int i=1;i<=m;i++) printf("%d\n",ans[i]); }