动态开点的权值线段树搞普通平衡树。。。补发一波

本文介绍了一种使用段式树状数组实现高效查询和更新操作的方法,详细讲解了其在离散数值范围内的应用,包括添加、删除、查找排名、获取前驱和后继等操作,适用于算法竞赛和复杂数据结构的学习。

RT.

#include<iostream>
#include<cstdio>
#define R register int
using namespace std; 
inline int g() {
    R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix;
    do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix;
}
const int N=100010,Inf=1E+7+10; 
struct node {int ls,rs,cnt;}t[N<<2];
int n,tot,rt;
#define ls t[tr].ls
#define rs t[tr].rs
#define cnt(x) t[x].cnt
inline void add(int& tr,int l,int r,int vl,int d) {
    if(!tr) tr=++tot; if(l==r) {cnt(tr)+=d; return ;} R md=l+r>>1;
    if(vl<=md) add(ls,l,md,vl,d); else add(rs,md+1,r,vl,d); cnt(tr)=cnt(ls)+cnt(rs);
}
inline int query(int tr,int l,int r,int LL,int RR) {
    if(!tr) return 0; if(LL<=l&&r<=RR) return cnt(tr); R md=l+r>>1,ret=0;
    if(LL<=md) ret+=query(ls,l,md,LL,RR); if(RR>md) ret+=query(rs,md+1,r,LL,RR); return ret;
}
inline int getvl(int tr,int l,int r,int rk) {
    if(l==r) return l; R md=l+r>>1;
    if(cnt(ls)>=rk) return getvl(ls,l,md,rk); else return getvl(rs,md+1,r,rk-cnt(ls));
}
inline int getrk(int tr,int l,int r,int vl) { if(!tr) return 0;
    if(l==r) return 1; R md=l+r>>1;
    if(vl<=md) return getrk(ls,l,md,vl); else return cnt(ls)+getrk(rs,md+1,r,vl);
}
inline int getpre(int vl) {R rk=query(1,-Inf,Inf,-Inf,vl-1); return getvl(1,-Inf,Inf,rk);}
inline int getnxt(int vl) {R rk=query(1,-Inf,Inf,-Inf,vl)+1; return getvl(1,-Inf,Inf,rk);}
signed main() {
#ifdef JACK
    freopen("NOIPAK++.in","r",stdin);
#endif
    n=g(); for(R i=1,op,x;i<=n;++i) {
        op=g(),x=g(); if(op==1) add(rt,-Inf,Inf,x,1); else if(op==2) add(rt,-Inf,Inf,x,-1);
        else if(op==3) printf("%d\n",getrk(1,-Inf,Inf,x)); 
        else if(op==4) printf("%d\n",getvl(1,-Inf,Inf,x));
        else if(op==5) printf("%d\n",getpre(x));
        else if(op==6) printf("%d\n",getnxt(x));    
    }
}

2019.07.03

 

转载于:https://www.cnblogs.com/Jackpei/p/11128437.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值