ANJHZ的博客

2021.08.10 静态区间第k小

离散化后用可持久化权值线段树处理。

查询的时候比较第r个版本和第l-1个版本的信息,若左结点cnt之差>=k,说明答案在左结点,递归query(左结点,k),否则答案在右结点,递归query(右结点,k-左结点cnt之差)。

可持久化线段树的写法参考:2021.08.10 可持久化线段树 - ANJHZ - 博客园 (cnblogs.com)

代码对应的模板是洛谷 P3834 【模板】可持久化线段树 2:

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+11;
const int M=2e5+11;
int n,m,tot,top,root[N],nys[N]; 
struct seq
{
    int ord,val,ys;
}a[N];
struct CharimanTree
{
    int l,r,cnt;
}t[N<<5];
int cmp1(const struct seq &p,const struct seq &q){return p.val<q.val;}
int cmp2(const struct seq &p,const struct seq &q){return p.ord<q.ord;}
int buildtree(int l,int r)
{
    int now=++top;
    if(l==r) return now;
    int mid=(l+r)/2;
    t[now].l=buildtree(l,mid);
    t[now].r=buildtree(mid+1,r);
    return now;
}
int clone(int now)
{
    t[++top]=t[now];
    return top;
}
void update(int now)
{
    t[now].cnt=0;
    if(t[now].l) t[now].cnt+=t[t[now].l].cnt;
    if(t[now].r) t[now].cnt+=t[t[now].r].cnt;
}
int modify(int now,int l,int r,int pos,int pls)
{
    now=clone(now);
    if(l==r)
    {
        t[now].cnt+=pls;
        return now;
    }
    int mid=(l+r)/2;
    if(pos<=mid) t[now].l=modify(t[now].l,l,mid,pos,pls);
    else t[now].r=modify(t[now].r,mid+1,r,pos,pls);
    update(now);
    return now;
}
int query(int rnow,int lnow,int l,int r,int k)
{
    if(t[rnow].cnt-t[lnow].cnt<k) return -2e9;
    if(l==r) return l;
    int mid=(l+r)/2;
    if(t[t[rnow].l].cnt-t[t[lnow].l].cnt>=k) return query(t[rnow].l,t[lnow].l,l,mid,k);
    else return query(t[rnow].r,t[lnow].r,mid+1,r,k-(t[t[rnow].l].cnt-t[t[lnow].l].cnt));
}
int main()
{
    int i,l,r,k;
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++)
    {
        scanf("%d",&a[i].val);
        a[i].ord=i;
    }
    sort(a+1,a+n+1,cmp1);
    for(i=1;i<=n;i++)
    {
        if(i==1||a[i].val!=a[i-1].val) a[i].ys=++tot,nys[tot]=a[i].val;
        else a[i].ys=tot;
    }
    sort(a+1,a+n+1,cmp2);
    
    root[0]=buildtree(1,tot);
    for(i=1;i<=n;i++)root[i]=modify(root[i-1],1,tot,a[i].ys,1);
    for(i=1;i<=m;i++)
    {
        scanf("%d%d%d",&l,&r,&k);
        printf("%d\n",nys[query(root[r],root[l-1],1,tot,k)]);
    }
    return 0;
}

 

posted on 2021-08-10 17:38  ANJHZ  阅读(78)  评论(0)    收藏  举报

导航