1. 程式人生 > WINDOWS開發 >AcWing255 第K小數(整體二分)

AcWing255 第K小數(整體二分)

這題還有一種做法是整體二分,其實本質上就是權值線段樹上二分

另外注意的一點是,負數的時候/2和右移有些許區別。

技術分享圖片
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
struct node{
    int op,x,y,k,id;
}q[N],lq[N],rq[N];
int ans[N];
int tr[N];
int lowbit(int x){  //lowbit函式
    return x&-x;
}
void add(int x,int c){  //
單點修改函式 int i; for(i=x;i<=N;i+=lowbit(i)){ tr[i]+=c; } } int sum(int x){//區間查詢函式 int res=0; int i; for(i=x;i;i-=lowbit(i)){ res+=tr[i]; } return res; } void solve(int vl,int vr,int ql,int qr){ if(ql>qr){ return ; } if(vl==vr){
for(int i=ql;i<=qr;i++){ if(q[i].op==2) ans[q[i].id]=vl; } return ; } int mid=vl+vr>>1; int tmp1=0,tmp2=0; for(int i=ql;i<=qr;i++){ if(q[i].op==1){ if(q[i].x<=mid) add(q[i].y,1),lq[++tmp1]=q[i]; else
rq[++tmp2]=q[i]; } if(q[i].op==2){ int n=sum(q[i].y)-sum(q[i].x-1); if(n>=q[i].k){ lq[++tmp1]=q[i]; } else{ q[i].k-=n; rq[++tmp2]=q[i]; } } } for(int i=ql;i<=qr;i++){ if(q[i].op==1){ if(q[i].x<=mid) add(q[i].y,-1); } } for(int i=1;i<=tmp1;i++) q[ql+i-1] = lq[i]; for(int i=1;i<=tmp2;i++) q[ql+tmp1+i-1] = rq[i]; solve(vl,mid,ql,ql+tmp1-1); solve(mid+1,vr,ql+tmp1,qr); } int main(){ int n,m; cin>>n>>m; int i; for(i=1;i<=n;i++){ int x; scanf("%d",&x); q[i]=node{1,i}; } for(i=1;i<=m;i++){ int l,r,k; scanf("%d%d%d",&l,&r,&k); q[i+n]=node{2,l,i}; } solve(-1e9,1e9,1,n+m); for(i=1;i<=m;i++) printf("%d\n",ans[i]); return 0; }
View Code