浅谈第k大

· · 个人记录

由于我比较菜,所以有什么错误请尽管提出,感谢!

什么是第k大?

就是把一段序列按从小到大排序,下标规定从1开始,下标为k的数即为此段序列的第k大。

如何解决?

下文中将使用长度为 na 序列,数列最大值为 V ,并用 O()-O()-O() 表示预处理时间复杂度,单次查询时间复杂度,空间复杂度。

1.一个 naive 的想法,使用 sort 使数组有序,然后输出下标为 k 的数。显然,这样做的复杂度是 O(1)-O(n \log n)-O(n) 的。

2.我们发现,我们并不需要整个数组有序,只找出第k大就好了,那么可以利用快速排序分治的思想,每次递归中随机选取一个数记为 pos ,将序列分为 3 段,即 [l,pos-1],[pos,pos],[pos+1,r] 使得第一段的数均小于 a[pos] ,第三段的数均大于 a[pos] ,判断下 pos 是否等于 k 即可。

3.我们又有一个 navie 的想法,我们可以开个桶去记录啊!然后暴力枚举 [1,V] 的数,开个 res 累计下数量是否到 k 即可。显然,这样复杂度是 O(n)-O(V)-O(V) 的。

4.我们发现,我们桶的思想就是枚举到 i 时,知道了小于等于 i 的数的数量,并判断这个数量是否大于等于k。

5.对顶堆

6.权值线段树

7.平衡树

8.序列分块套二分(支持区间第 k 大)

9.值域分块套序列分块(支持区间第 k 大)

10.主席树(静态区间第 k 大)

11.树套树(动态区间第k大)

12.整体二分(离线,动态区间第k大)

13.莫队维护区间树状数组做到区间第k大 (离线)

接下来是一些奇怪的第 k 大。

1.矩阵第 k

2.树上路径第 k

Code:

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cmath>
#include <vector>

#define N (int)(1e5+5)
#define SN (int)(1e3+5)
#define il inline
#define fp(i,qaq,qwq) for(int i=(qaq);i<=(qwq);++i)
#define fd(i,qaq,qwq) for(int i=(qaq);i>=(qwq);--i)
#define id(xgf) ((xgf-1)/blk+1)

using namespace std;

int b[SN][SN],cnt[SN],tag[SN],a[N],gr[SN][2];
int n,m,blk;

il int rd() {
    int f=1,sum=0; char ch=getchar();
    while(!isdigit(ch)) {
        if(ch=='-') f=-1;
        ch=getchar();
    }
    while(isdigit(ch)) {
        sum=(sum<<3)+(sum<<1)+ch-'0';
        ch=getchar();
    }
    return sum*f;
}

il void pr(int x) {
    if(x<0) {
        putchar('-');
        x=-x;
    }
    if(x>9) pr(x/10);
    putchar(x%10+'0');
}

il void reset(int x) {
    cnt[x]=0;
    fp(i,gr[x][0],gr[x][1]) b[x][cnt[x]++]=a[i];
    sort(b[x],b[x]+cnt[x]);
}

il void update(int x,int y,int z) {
    if(id(x)==id(y)) {
        fp(i,x,y) a[i]+=z;
        reset(id(x));
    } else {
        fp(i,x,gr[id(x)][1]) a[i]+=z;
        reset(id(x));
        fp(i,id(x)+1,id(y)-1) tag[i]+=z;
        fp(i,gr[id(y)][0],y) a[i]+=z;
        reset(id(y));
    }
}

il int get_ans(int x,int y,int z) {
    if(id(x)==id(y)) {
        int tot=0;
        fp(i,x,y) if(a[i]+tag[id(x)]<=z) ++tot;
        return tot;
    } else {
        int tot=0;
        fp(i,x,gr[id(x)][1]) if(a[i]+tag[id(x)]<=z) ++tot;
        fp(i,gr[id(y)][0],y) if(a[i]+tag[id(y)]<=z) ++tot;
        fp(i,id(x)+1,id(y)-1) tot+=(b[i][cnt[i]-1]+tag[i])<=z?cnt[i]:(b[i][0]+tag[i]>z)?0:upper_bound(b[i],b[i]+cnt[i],z-tag[i])-b[i];
        return tot;
    }
}

il int qry(int x,int y,int z) {
    int answ=-1,l=-2e9,r=(int)(2e9);
    while(l<=r) {
        int mid=(l+r)>>1;
        if(get_ans(x,y,mid)>=z) answ=mid,r=mid-1;
        else l=mid+1;
    }
    return answ;
}

signed main() {
    n=rd(); m=rd(); blk=pow(n*log(n),0.425);
    int op,x,y,z,tmp=-1;
    fp(i,1,n) {
        a[i]=rd();
        if(id(i)!=tmp) gr[id(i)][0]=i,tmp=id(i);
        else gr[id(i)][1]=i;
        b[id(i)][cnt[id(i)]++]=a[i];
    }
    fp(i,1,id(n)) sort(b[i],b[i]+cnt[i]);
    fp(i,1,m) {
        op=rd(); x=rd(); y=rd(); z=rd();
        if(op==1) {
            pr(qry(x,y,z));
            puts("");
        } else {
            update(x,y,z);
        }
    }
    return 0;
}
#include <bits/stdc++.h>

#define N (int)(1e5+20)
#define M 320

using namespace std;

int n,m,sz,bl[N],a[N],L[M],R[M],cnt1[M][M],cnt2[M][N],sum1[M],sum2[N],id[M][N],rid[M][N],pos[N];

int rd() {
    int f=1,sum=0; char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
    return sum*f;
}

void pr(int x) {
    if(x<0) {putchar('-');x=-x;}
    if(x>9) pr(x/10);
    putchar(x%10+'0');
}

void build(int x) {
    int tot=0;
    for(int i=1;i<=sz;i++) id[x][rid[x][i]]=0;
    for(int i=L[x];i<=R[x];i++) {
        if(!id[x][a[i]]) id[x][a[i]]=++tot,rid[x][tot]=a[i];
        pos[i]=id[x][a[i]];
    }
}

void push_down(int x) {
    for(int i=L[x];i<=R[x];i++) a[i]=rid[x][pos[i]]; 
}

void solve(int l,int r,int x,int y) {
    for(int i=l;i<=r;i++) {
        if(a[i]==x) {
            --cnt1[bl[l]][bl[x]]; --cnt2[bl[l]][x];
            ++cnt1[bl[l]][bl[y]]; ++cnt2[bl[l]][y];
            a[i]=y;
        }
    }
}

void update(int l,int r,int x,int y) {
    if(x==y||cnt2[bl[r]][x]-cnt2[bl[l]-1][x]==0) return;
    for(int i=bl[n];i>=bl[l];i--) cnt2[i][x]-=cnt2[i-1][x],cnt2[i][y]-=cnt2[i-1][y],cnt1[i][bl[x]]-=cnt1[i-1][bl[x]],cnt1[i][bl[y]]-=cnt1[i-1][bl[y]];
    if(bl[l]==bl[r]) {
        push_down(bl[l]);
        solve(l,r,x,y);
        build(bl[l]);
    } else {
        push_down(bl[l]); push_down(bl[r]);
        solve(l,R[bl[l]],x,y); solve(L[bl[r]],r,x,y);
        build(bl[l]); build(bl[r]);
        for(int i=bl[l]+1;i<bl[r];i++) {
            if(!cnt2[i][x]) continue;
            if(cnt2[i][y]) {
                push_down(i);
                solve(L[i],R[i],x,y);
                build(i);
            } else {
                cnt1[i][bl[y]]+=cnt2[i][x]; cnt1[i][bl[x]]-=cnt2[i][x];
                cnt2[i][y]=cnt2[i][x]; cnt2[i][x]=0;
                id[i][y]=id[i][x]; rid[i][id[i][x]]=y; id[i][x]=0;
            }
        }
    }
    for(int i=bl[l];i<=bl[n];i++) cnt2[i][x]+=cnt2[i-1][x],cnt2[i][y]+=cnt2[i-1][y],cnt1[i][bl[x]]+=cnt1[i-1][bl[x]],cnt1[i][bl[y]]+=cnt1[i-1][bl[y]];
}

int kth(int l,int r,int k) {
    int sum=0;
    if(bl[l]==bl[r]) {
        push_down(bl[l]);
        for(int i=l;i<=r;i++) sum2[i]=a[i];
        nth_element(sum2+l,sum2+l+k-1,sum2+r+1); int answ=sum2[l+k-1];
        for(int i=l;i<=r;i++) sum2[i]=0;
        return answ;
    }
    push_down(bl[l]); push_down(bl[r]);
    for(int i=l;i<=R[bl[l]];i++) ++sum1[bl[a[i]]],++sum2[a[i]];
    for(int i=L[bl[r]];i<=r;i++) ++sum1[bl[a[i]]],++sum2[a[i]];
    for(int i=1;i<=(N-1)/sz+1;++i) {
        if(sum+sum1[i]+cnt1[bl[r]-1][i]-cnt1[bl[l]][i]>=k){
            for(int j=(i-1)*sz+1;j<=i*sz;++j)
                if(sum+sum2[j]+cnt2[bl[r]-1][j]-cnt2[bl[l]][j]>=k){
                    for(int o=l;o<=R[bl[l]];++o) --sum1[bl[a[o]]],--sum2[a[o]];
                    for(int o=L[bl[r]];o<=r;++o) --sum1[bl[a[o]]],--sum2[a[o]]=0;
                    return j;
                }
                else sum+=sum2[j]+cnt2[bl[r]-1][j]-cnt2[bl[l]][j];
        }
        else sum+=sum1[i]+cnt1[bl[r]-1][i]-cnt1[bl[l]][i];
    }
}

int main() {
    n=rd(); m=rd(); sz=sqrt(n);
    for(int i=1;i<N;i++) bl[i]=(i-1)/sz+1;
    for(int i=1;i<=n;i++) a[i]=rd();
    for(int i=1;i<=bl[n];i++) L[i]=(i-1)*sz+1,R[i]=i*sz; R[bl[n]]=n;
    for(int i=1;i<=bl[n];i++) build(i);
    for(int x=1;x<=bl[n];x++) {
        for(int i=1;i<=bl[N-1];i++) cnt1[x][i]=cnt1[x-1][i];
        for(int i=1;i<N;i++) cnt2[x][i]=cnt2[x-1][i];
        for(int i=L[x];i<=R[x];i++) ++cnt1[x][bl[a[i]]],++cnt2[x][a[i]];
    }
    int op,l,r,x,y;
    while(m--) {
        op=rd(); l=rd(); r=rd(); x=rd();
        if(op==1) y=rd(),update(l,r,x,y);
        else pr(kth(l,r,x)),puts("");
    }
    return 0;
}
#include <bits/stdc++.h>

#define N (int)(7e4+5)
#define M 1000
#define ED puts("")
#define il inline
il int rd() {
    int f=1,sum=0; char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
    return sum*f;
}

il void pr(int x) {
    if(x<0) {putchar('-');x=-x;}
    if(x>9) pr(x/10);
    putchar(x%10+'0');
}

char nex() {
    char ch=getchar();
    while(!isalpha(ch)) ch=getchar();
    return ch;
}

using namespace std;

struct node {
    int l,r,sz,cnt1[M],cnt2[N],a[M];
    int& operator [](const int k) {
        return a[k];
    }
}g[M];

int id[N],sum1[M],sum2[N];
int n,m,bl,tot;

il int kth(int l,int r,int k) {
    int lb,rb,no=1,qwq=1,res=0;
    while(g[no].sz<l) l-=g[no].sz,no=g[no].r;
    lb=no; no=1;
    while(g[no].sz<r) r-=g[no].sz,no=g[no].r;
    rb=no;
    //cout<<l<<" "<<r<<" "<<k<<" "<<lb<<" this is question "<<rb<<endl;
    if(lb==rb) {
        for(int i=l;i<=r;i++) {
            ////cout<<val[lb][i]<<" ";
            ++sum1[id[g[lb][i]]],++sum2[g[lb][i]];
        }
        qwq=1;
        while(sum1[qwq]<k) k-=sum1[qwq],++qwq;
        qwq=(qwq-1)*bl; //cout<<qwq<<endl;
        while(sum2[qwq]<k) k-=sum2[qwq],++qwq; 
        for(int i=l;i<=r;i++) sum1[id[g[lb][i]]]=0,sum2[g[lb][i]]=0;
        return qwq;
    }
    qwq=1;
    for(int i=l;i<=g[lb].sz;i++) {
        ++sum1[id[g[lb][i]]],++sum2[g[lb][i]];
    }
    for(int i=1;i<=r;i++) ++sum1[id[g[rb][i]]],++sum2[g[rb][i]];
    while(sum1[qwq]+g[g[rb].l].cnt1[qwq]-g[lb].cnt1[qwq]<k) {
        k-=sum1[qwq]+g[g[rb].l].cnt1[qwq]-g[lb].cnt1[qwq]; ++qwq;
    }
    qwq=(qwq-1)*bl; //cout<<qwq<<endl;
    while(sum2[qwq]+g[g[rb].l].cnt2[qwq]-g[lb].cnt2[qwq]<k) {
        k-=sum2[qwq]+g[g[rb].l].cnt2[qwq]-g[lb].cnt2[qwq]; ++qwq;
    }
    for(int i=l;i<=g[lb].sz;i++) --sum1[id[g[lb][i]]],--sum2[g[lb][i]];
    for(int i=1;i<=r;i++) --sum1[id[g[rb][i]]],--sum2[g[rb][i]];
    return qwq;
}

il void update(int x,int v) {
//  //cout<<x<<" "<<v<<endl;
    int b,no=1,pre_v;
    while(g[no].sz<x) {
        x-=g[no].sz,no=g[no].r;
//      //cout<<x<<" "<<no;
    }
    b=no; pre_v=g[b][x];
    if(pre_v==v) return;
    g[b][x]=v;
    for(int i=b;i;i=g[i].r) {
        --g[i].cnt1[id[pre_v]]; --g[i].cnt2[pre_v];
        ++g[i].cnt1[id[v]]; ++g[i].cnt2[v];
    }
}

il void split(int x) {
    int b=++tot;
    g[b].r=g[x].r; g[g[x].r].l=b; g[x].r=b; g[b].l=x;
    g[b].sz=g[x].sz/2;
    int tmp=g[x].sz-g[b].sz;
    memcpy(g[b].cnt1,g[x].cnt1,sizeof(g[x].cnt1));
    memcpy(g[b].cnt2,g[x].cnt2,sizeof(g[x].cnt2));
    for(int i=tmp+1;i<=g[x].sz;i++) {
        g[b][i-tmp]=g[x][i];
        --g[x].cnt1[id[g[x][i]]]; --g[x].cnt2[g[x][i]];
        g[x][i]=0;
    }
    g[x].sz=tmp;
}

il void insert(int x,int v) {
    int b,no=1;
    while(g[no].sz<x) {
        if(g[no].r) x-=g[no].sz,no=g[no].r;
        else break;
    }
    b=no; //cout<<b<<endl;
    for(int i=g[b].sz;i>=x;i--) g[b][i+1]=g[b][i];
    g[b][x]=v; ++g[b].sz;
    for(int i=b;i;i=g[i].r) {
        ++g[i].cnt1[id[v]]; ++g[i].cnt2[v];
    }
    if(g[b].sz>2*bl) split(b);
}

int main() {
    char op; int x,y,z,las=0;
    n=rd(); bl=400; 
    for(int i=0;i<=N-5;i++) id[i]=i/bl+1; tot=id[n];
    for(int i=1;i<=n;i++) x=rd(),g[id[i]][++g[id[i]].sz]=x;
    m=rd();
    for(int i=1;i<=id[n];i++) g[i].l=i-1,g[i].r=i+1; g[1].l=g[id[n]].r=0;
    for(int x=1;x<=id[n];x++) {
        for(int i=1;i<=g[x].sz;i++) ++g[x].cnt1[id[g[x][i]]],++g[x].cnt2[g[x][i]];
        for(int i=0;i<=N-5;i++) {
            if(!i||id[i]!=id[i-1]) g[x].cnt1[id[i]]+=g[x-1].cnt1[id[i]];
            g[x].cnt2[i]+=g[x-1].cnt2[i];
        }
    }   
    while(m--) {
        op=nex();
        if(op=='Q') {
            x=rd()^las; y=rd()^las; z=rd()^las;
            pr(las=kth(x,y,z)); ED;
        } else if(op=='M') {
            x=rd()^las; y=rd()^las;
            update(x,y);
        } else if(op=='I') {
            x=rd()^las; y=rd()^las;
            insert(x,y); 
        }
    }

    return 0;
}
#include <bits/stdc++.h>

#define N (int)(5e5+5)
#define ED puts("")

using namespace std;

struct node {
    int typ,l,r,val,id;
}q[N],q1[N],q2[N];

int sum[N];
int n,m,tot,cnt,ans[N],lsh[N],pre[N],lcnt;

int rd() {
    int f=1,sum=0; char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
    return sum*f;
}

void pr(int x) {
    if(x<0) {putchar('-');x=-x;}
    if(x>9) pr(x/10);
    putchar(x%10+'0');
}

int lowbit(int x) {
    return x&(-x);
}

void add(int x,int y) {
    while(x<=n) sum[x]+=y,x+=lowbit(x);
}

int qry(int x) {
    int res=0;
    while(x) res+=sum[x],x-=lowbit(x);
    return res;
}

void solve(int l,int r,int L,int R) {
    if(l>r||L>R) return;
    int cnt1=0,cnt2=0,mid=(l+r)>>1;
    if(l==r) {
        for(int i=L;i<=R;i++) if(q[i].typ==2) ans[q[i].id]=lsh[l];
        return;
    }
    for(int i=L;i<=R;i++) {
        if(q[i].typ==2) {
            int qwq=qry(q[i].r)-qry(q[i].l-1);
            if(q[i].val<=qwq) q1[++cnt1]=q[i];
            else q[i].val-=qwq,q2[++cnt2]=q[i];
        } else {
            if(q[i].val<=mid) add(q[i].l,q[i].r),q1[++cnt1]=q[i];
            else q2[++cnt2]=q[i];
        }
    }
    for(int i=1;i<=cnt1;i++) if(q1[i].typ==1) add(q1[i].l,-q1[i].r);
    for(int i=1;i<=cnt1;i++) q[L+i-1]=q1[i];
    for(int i=1;i<=cnt2;i++) q[cnt1+L+i-1]=q2[i];
    solve(l,mid,L,L+cnt1-1); solve(mid+1,r,L+cnt1,R);
}

int main() {
    n=rd(); m=rd();
    char op[2]; int l,r,x;
    for(int i=1;i<=n;i++) {
        x=rd();
        q[++tot]=node{1,i,1,x,0};
        lsh[++lcnt]=x; pre[i]=x;
    }   
    for(int i=1;i<=m;i++) {
        cin>>op; l=rd(); r=rd();
        if(op[0]=='Q') {
            x=rd();
            q[++tot]=node{2,l,r,x,++cnt};
        } else {
            q[++tot]=node{1,l,-1,pre[l],0};
            q[++tot]=node{1,l,1,r,0};
            lsh[++lcnt]=r; pre[l]=r;
        }
    }
    sort(lsh+1,lsh+1+lcnt); lcnt=unique(lsh+1,lsh+1+lcnt)-lsh;
    for(int i=1;i<=tot;i++) {
        if(q[i].typ==1) q[i].val=lower_bound(lsh+1,lsh+1+lcnt,q[i].val)-lsh;
    }
    solve(1,lcnt,1,tot);
    for(int i=1;i<=cnt;i++) pr(ans[i]),ED;
    return 0; 
}
#include <bits/stdc++.h>

#define N (int)(1e5+5)

using namespace std;

int rt[N],cx[20],cy[20],a[N];
int n,m,tot,totx,toty;

struct BIT {
    int ls[N*500],rs[N*500],sum[N*500];
    void update(int &cur,int l,int r,int x,int val) {
        if(!cur) cur=++tot;
        sum[cur]+=val;
        if(l==r) return;
        int mid=(l+r)>>1;
        if(x<=mid) update(ls[cur],l,mid,x,val);
        else update(rs[cur],mid+1,r,x,val);
    }
    int query(int l,int r,int k) {
        if(l==r) return l;
        int mid=(l+r)>>1,res=0;
        for(int i=1;i<=totx;i++) res+=sum[ls[cx[i]]];
        for(int i=1;i<=toty;i++) res-=sum[ls[cy[i]]];
        if(k<=res) {
            for(int i=1;i<=totx;i++) cx[i]=ls[cx[i]];
            for(int i=1;i<=toty;i++) cy[i]=ls[cy[i]];
            return query(l,mid,k);
        } else {
            for(int i=1;i<=totx;i++) cx[i]=rs[cx[i]];
            for(int i=1;i<=toty;i++) cy[i]=rs[cy[i]];
            return query(mid+1,r,k-res);
        }
    }
}T;

int lowbit(int x) {
    return x&(-x);
}

void modify(int pos,int x,int val) {
    for(;pos<=n;pos+=lowbit(pos)) T.update(rt[pos],0,1e9,x,val);
}

int rd() {
    int f=1,sum=0; char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
    return sum*f;
}

int main() {
    n=rd(); m=rd();
    for(int i=1;i<=n;i++) a[i]=rd(),modify(i,a[i],1);
    char op; int l,r,x;
    while(m--) {
        cin>>op; l=rd(); r=rd();
        if(op=='Q') {
            x=rd();
            totx=toty=0;
            for(int i=r;i;i-=lowbit(i)) cx[++totx]=rt[i];
            for(int i=l-1;i;i-=lowbit(i)) cy[++toty]=rt[i];
            printf("%d\n",T.query(0,1e9,x));
        } else {
            modify(l,a[l],-1); modify(l,a[l]=r,1);
        }
    }
}
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>

#define M 505
#define N (int)(3e5+5)

using namespace std;

struct node {
    int x,y,val;
}a[N];

struct ques {
    int x,y,xx,yy,k,id;
}q[N];

int sum[M][M];
int n,m,ans[N];

int rd() {
    int f=1,sum=0; char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
    return sum*f;
}

bool cmp(node x,node y) {
    return x.val<y.val;
}

int lowbit(int x) {
    return x&(-x);
}

void add(int x,int y,int val) {
    int ny;
    while(x<=n) {
        ny=y;
        while(ny<=n) {
            sum[x][ny]+=val;
            ny+=lowbit(ny);
        }
        x+=lowbit(x);
    }
}

int qry(int x,int y) {
    int res=0,ny;
    if(!x||!y) return 0;
    while(x) {
        ny=y;
        while(ny) {
            res+=sum[x][ny];
            ny-=lowbit(ny);
        }
        x-=lowbit(x);
    }
    return res;
}

int query(int x,int y,int xx,int yy) {
    return qry(xx,yy)+qry(x-1,y-1)-qry(x-1,yy)-qry(xx,y-1);
}

ques t1[N],t2[N];
void solve(int L,int R,int l,int r) {
    if(L==R) {
        for(int i=l;i<=r;i++) {
            //cout<<q[i].k<<":";
            ans[q[i].id]=a[L].val;
        }
        return;
    }
    int mid=(L+R)>>1,cnt1=0,cnt2=0;
    for(int i=L;i<=mid;i++) add(a[i].x,a[i].y,1);
    for(int i=l;i<=r;i++) {
        int res=query(q[i].x,q[i].y,q[i].xx,q[i].yy);
        if(res>=q[i].k) t1[++cnt1]=q[i];
        else q[i].k-=res,t2[++cnt2]=q[i];
    //  cout<<":xgf "<<res<<" "<<i<<" "<<q[i].k<<" "<<L<<' '<<R<<endl;
    }
    for(int i=L;i<=mid;i++) add(a[i].x,a[i].y,-1);
    for(int i=1;i<=cnt1;i++) q[i+l-1]=t1[i];
    for(int i=1;i<=cnt2;i++) q[i+cnt1+l-1]=t2[i];
    solve(L,mid,l,l+cnt1-1); solve(mid+1,R,l+cnt1,r);
}

int main() {
    n=rd(); m=rd();
    int tot=0;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++) 
            a[++tot]=node{i,j,rd()};
    sort(a+1,a+1+tot,cmp);
    for(int i=1;i<=m;i++) {
        q[i]=ques{rd(),rd(),rd(),rd(),rd(),i};
    }
    solve(1,tot,1,m);
    for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
    return 0;
} 
#include <bits/stdc++.h>

#define N (int)(3e5+5)
#define ls (cur<<1)
#define rs (ls|1)

using namespace std;

struct node {
    int x,y,val,id;
}a[N<<1];

struct edge {
    int nex,to;
}e[N<<1];

bool vis[N];
int head[N],cnt,tot,fa[N],top[N],dep[N],son[N],id[N],sz[N];
int n,m,pre[N],lsh[N],ans[N],l_cnt;

int rd() {
    int f=1,sum=0; char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
    return sum*f;
}

void add(int x,int y) {
    e[++cnt]=edge{head[x],y};
    head[x]=cnt;
}

void dfs1(int x,int faa) {
    dep[x]=dep[faa]+1; fa[x]=faa; sz[x]=1;
    for(int i=head[x];i;i=e[i].nex) {
        int y=e[i].to;
        if(y==faa) continue;
        dfs1(y,x); sz[x]+=sz[y];
        if(sz[y]>sz[son[x]]) son[x]=y;
    }
}

void dfs2(int x,int tp) {
    top[x]=tp; id[x]=++tot;
    if(son[x]) dfs2(son[x],tp);
    for(int i=head[x];i;i=e[i].nex) {
        int y=e[i].to;
        if(y==fa[x]||y==son[x]) continue;
        dfs2(y,y);
    }
}

int sum[N<<2];
void add(int cur,int l,int r,int x,int val) {
    if(l==r) {
        sum[cur]+=val;
        return;
    }
    int mid=(l+r)>>1;
    if(x<=mid) add(ls,l,mid,x,val);
    else add(rs,mid+1,r,x,val);
    sum[cur]=sum[ls]+sum[rs];
}

int query(int cur,int l,int r,int cl,int cr) {
    if(cl>cr) return 0;
    if(cl<=l&&r<=cr) return sum[cur];
    int mid=(l+r)>>1,res=0;
    if(cl<=mid) res=query(ls,l,mid,cl,cr);
    if(cr>mid) res+=query(rs,mid+1,r,cl,cr);
    return res;
}

int qry(int x,int y) {
    int res=0;
    while(top[x]!=top[y]) {
        if(dep[top[x]]<dep[top[y]]) swap(x,y);//cout<<x<<" "<<y<<endl;
        res+=query(1,1,n,id[top[x]],id[x]);
        x=fa[top[x]];
    }
    if(id[x]>id[y]) swap(x,y);
    return res+query(1,1,n,id[x],id[y]);
}

node q1[N],q2[N];
void solve(int L,int R,int l,int r) {
    if(l>r) return;
    if(L==R) {
        for(int i=l;i<=r;i++) {
            if(a[i].id==-1) continue;
            ans[a[i].id]=lsh[L];
        //  cout<<lsh[L]<<" "<<a[i].val<<endl;
        }
        //cout<<L<<" "<<l<<" "<<r<<endl;
        return;
    }
    int mid=(L+R)>>1,cnt1=0,cnt2=0;
    for(int i=l;i<=r;i++) {
        if(a[i].id==-1) {
            if(a[i].val<=mid) q1[++cnt1]=a[i];
            else q2[++cnt2]=a[i],add(1,1,n,id[a[i].x],a[i].y);
        } else {
            int res=qry(a[i].x,a[i].y);
            if(res>=a[i].val) q2[++cnt2]=a[i];
            else a[i].val-=res,q1[++cnt1]=a[i];
        }
    }
    for(int i=1;i<=cnt2;i++) if(q2[i].id==-1) add(1,1,n,id[q2[i].x],-q2[i].y);
    for(int i=1;i<=cnt1;i++) a[i+l-1]=q1[i];
    for(int i=1;i<=cnt2;i++) a[i+l+cnt1-1]=q2[i];
    solve(L,mid,l,l+cnt1-1); solve(mid+1,R,l+cnt1,r);
}

int main() {
    n=rd(); m=rd();
    int tot1=0,x,y;
    for(int i=1;i<=n;i++) pre[i]=rd(),a[++tot1]=node{i,1,pre[i],-1},lsh[++l_cnt]=pre[i];
    for(int i=1;i<n;i++) x=rd(),y=rd(),add(x,y),add(y,x);
    dfs1(1,0); dfs2(1,1);   
    for(int i=1;i<=m;i++) {
        x=rd();
        if(x==0) {
            x=rd(); y=rd();
            a[++tot1]=node{x,-1,pre[x],-1};
            a[++tot1]=node{x,1,y,-1};
            lsh[++l_cnt]=pre[x]=y;
        } else {
            a[++tot1]=node{rd(),rd(),x,i};
            vis[i]=1;
        }
    }
    sort(lsh+1,lsh+1+l_cnt);// l_cnt=unique(lsh+1,lsh+1+l_cnt)-lsh-1;
    for(int i=1;i<=tot1;i++) {
        if(a[i].id==-1) a[i].val=lower_bound(lsh+1,lsh+1+l_cnt,a[i].val)-lsh;
    } 
    solve(0,l_cnt,1,tot1);
    for(int i=1;i<=m;i++) {
        if(vis[i]) ans[i]?printf("%d\n",ans[i]):puts("invalid request!");
    }
    return 0;
}
#include <bits/stdc++.h>

#define N (int)(2e5+5)

using namespace std;

struct ques {
    int l,r,k,id;
}q[N];

int n,m,bl,pos[N],ans[N],a[N],lsh[N],sum[N];

int rd() {
    int f=1,sum=0; char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
    return sum*f;
}

bool cmp(ques x,ques y) {
    return pos[x.l]==pos[y.l]?pos[x.l]&1?x.r<y.r:x.r>y.r:x.l<y.l;
}

int lowbit(int x) {
    return x&(-x);
}

void add(int x,int w) {
    if(!x) return; 
    while(x<N) {
        sum[x]+=w,x+=lowbit(x);
        //cout<<x<<endl;
    }
}

int qry(int x) {
    int res=0;
    while(x) res+=sum[x],x-=lowbit(x);
    return res;
}

int solve(int k) {
    int l=1,r=n,res=0;
    while(l<=r) {
        int mid=(l+r)>>1;
        if(qry(mid)>=k) res=mid,r=mid-1;
        else l=mid+1;
    }
    return lsh[res];
}

int main() {
    n=rd(); m=rd(); bl=sqrt(n);
    for(int i=1;i<=n;i++) pos[i]=(i-1)/bl+1,lsh[i]=a[i]=rd();
    sort(lsh+1,lsh+1+n);
    for(int i=1;i<=n;i++) a[i]=lower_bound(lsh+1,lsh+1+n,a[i])-lsh;
    //for(int i=1;i<=n;i++) cout<<a[i]<<" "; puts("");
    for(int i=1;i<=m;i++) {
        q[i]=ques{rd(),rd(),rd(),i};
    }
    sort(q+1,q+1+m,cmp);
    int l=0,r=0,cl,cr;
    for(int i=1;i<=m;i++) {
        cl=q[i].l; cr=q[i].r;
    //  cout<<cl<<" "<<cr<<endl;
        while(l<cl) add(a[l++],-1);
        while(l>cl) add(a[--l],1);
        while(r<cr) add(a[++r],1);
        while(r>cr) add(a[r--],-1);
        ans[q[i].id]=solve(q[i].k);
    }
    for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
    return 0;
}

参考资料:

https://www.cnblogs.com/fusiwei/p/11432323.html

https://oi-wiki.org/basic/quick-sort/

https://www.luogu.com.cn/blog/2-6-5-3-5/zheng-ti-er-fen-xie-jue-jing-tai-ou-jian-di-k-xiao-di-you-hua