整體二分求區間第k大
阿新 • • 發佈:2020-12-23
#include<stdio.h> #define inf 0x3f3f3f3f int s[200100]; void add(int x,int y){ for(int i=x;i<=200000;i=i+(i&(-i))){ s[i]+=y; } } int sum(int x){ int ans=0; for(int i=x;i>0;i=i-(i&(-i))){ ans=ans+s[i]; } return ans; } int ans[200100]; struct node{ int x,y,id,k,type; }a[400100],w[400100],e[400100]; void solve(int cs,int zd,int l,int r){ if(cs>zd||l>r)return ; if(l==r){ for(int i=cs;i<=zd;i++){ if(a[i].type==2){ ans[a[i].id]=l; } } return ; } int m=(l+r)/2; int t0=0,t1=0; for(int i=cs;i<=zd;i++){ if(a[i].type==1){ if(a[i].x<=m){ add(a[i].id,1); w[++t0]=a[i]; } else{ e[++t1]=a[i]; } } else{ int now=sum(a[i].y)-sum(a[i].x-1); if(now>=a[i].k){ w[++t0]=a[i]; } else{ a[i].k-=now; e[++t1]=a[i]; } } } for(int i=1;i<=t0;i++){ a[cs+i-1]=w[i]; } for(int i=1;i<=t1;i++){ a[cs+t0+i-1]=e[i]; } for(int i=cs;i<=zd;i++){ if(a[i].type==1&&a[i].x<=m){ add(a[i].id,-1); } } solve(cs,cs+t0-1,l,m); solve(cs+t0,cs+t0+t1-1,m+1,r); } int main(){ int cnt=0; int n,m; scanf("%d %d",&n,&m); for(int i=1;i<=n;i++){ int temp; scanf("%d",&temp); a[++cnt]=(node){temp,0,i,0,1}; } for(int i=1;i<=m;i++){ int l,r,z; scanf("%d %d %d",&l,&r,&z); a[++cnt]=(node){l,r,i,z,2}; } solve(1,cnt,-inf,inf); for(int i=1;i<=m;i++){ printf("%d\n",ans[i]); } }