码迷,mamicode.com
首页 > 其他好文 > 详细

sw抄来的主席树

时间:2021-04-15 12:28:09      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:space   div   +=   ==   lse   highlight   uniq   name   else   

//本模板是离散后对权值建树
#include<bits/stdc++.h>
#define mid (l+r>>1)
using namespace std;
const int N=2e5+10;
struct TR
{
    int sum,lo,ro;
}tr[N<<5];
int tr_cnt;//之后需要初始化=0
int n,m,q,arr[N],brr[N],rt[N];//m是权值的数量
void build(int &o,int l=1,int r=m)
{
    o=++tr_cnt;
    //tr[o].sum=0;
    if(l==r)return;
    build(tr[o].lo,l,mid);
    build(tr[o].ro,mid+1,r);
}
void update(int p,int v,int pre,int &o,int l=1,int r=m)
{
    o=++tr_cnt;
    tr[o]=tr[pre];
    tr[o].sum+=v;//都是+1
    if(l==r)return;
    if(p<=mid)update(p,v,tr[pre].lo,tr[o].lo,l,mid);
    else update(p,v,tr[pre].ro,tr[o].ro,mid+1,r);
}
//u和v是两个线段树的根,相减后的线段树求第k个的下标位置
int query(int k,int u,int v,int l=1,int r=m)
{
    if(l==r)return l;
 
    int tmp=tr[tr[v].lo].sum-tr[tr[u].lo].sum;
    if(tmp>=k)return query(k,tr[u].lo,tr[v].lo,l,mid);
    else return query(k-tmp,tr[u].ro,tr[v].ro,mid+1,r);
}
int main()
{
    int n,q;scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++)scanf("%d",arr+i),brr[i]=arr[i];
    sort(brr+1,brr+1+n);
    m=unique(brr+1,brr+1+n)-brr-1;
 
    build(rt[0]);
    for(int i=1;i<=n;i++)
    {
        int p=lower_bound(brr+1,brr+1+m,arr[i])-brr;
        update(p,1,rt[i-1],rt[i]);
    }
    while(q--)
    {
        int u,v,k;
        scanf("%d%d%d",&u,&v,&k);
        printf("%d\n",brr[query(k,rt[u-1],rt[v])]);
    }
	return 0;
}

  

sw抄来的主席树

标签:space   div   +=   ==   lse   highlight   uniq   name   else   

原文地址:https://www.cnblogs.com/LH2000/p/14659789.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!