[BZOJ3685]普通van Emde Boas树

面对BZOJ3685题目,普通的线段树和平衡树解决方案导致超时。然而,采用ZKW线段树能够有效地解决这一问题,实现快速求解,避免了TLE的情况。推荐阅读OLZ的相关论文《统计的力量》,并提供了AC代码。
摘要由CSDN通过智能技术生成

原题地址

用普通线段树\平衡树无限TLE!!!

然而ZKW线段树水过,OLZ神犇ZKW!!!

附论文《统计的力量》

AC code:

#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const int N=8000010;
const int INF=1<<29;
int n,m,first;

struct nod{
    int mx,mi;
};

struct Segtree{
    nod a[N];

    Segtree(){
        first=1<<(int)(log2(n+1)+2);
        for(int i=1;i<=(first<<1)-1;i++){
            a[i].mx=-INF;a[i].mi=INF;
        }
    }

    void insert(int x){
        int i=first+x+1;
        for(a[i].mx=a[i].mi=x,i>>=1;i;i>>=1){
            a[i].mx=max(a[i<<1].mx,a[(i<<1)^1].mx);
            a[i].mi=min(a[i<<1].mi,a[(i<<1)^1].mi);
        }
    }
    void erase(int x){
        int i=first+x+1;
        for(a[i].mx=-INF,a[i].mi=INF,i>>=1;i;i>>=1){
            a[i].mx=max(a[i<<1].mx,a[(i<<1)^1].mx);
            a[i].mi=min(a[i<<1].mi,a[(i<<1)^1].mi);
        }
    }
    void querymax(){
        printf("%d\n",a[1].mx!=-INF?a[1].mx:-1);
    }
    void querymin(){
        printf("%d\n",a[1].mi!=INF?a[1].mi:-1);
    }
    int getmax(int L,int R){
        int ans=-INF,i=first+L,j=first+R+2;
        for(;i+1!=j;i>>=1,j>>=1){
            if(!(i&1)) ans=max(ans,a[i^1].mx);
            if(j&1) ans=max(ans,a[j^1].mx);
        }
        return ans;
    }
    int getmin(int L,int R){
        int ans=INF,i=first+L,j=first+R+2;
        for(;i+1!=j;i>>=1,j>>=1){
            if(!(i&1)) ans=min(ans,a[i^1].mi);
            if(j&1) ans=min(ans,a[j^1].mi);
        }
        return ans;
    }
    void getpre(int x){
        int ans=getmax(0,x-1);
        printf("%d\n",ans!=-INF?ans:-1);
    }
    void getsuc(int x){
        int ans=getmin(x+1,n-1);
        printf("%d\n",ans!=INF?ans:-1);
    }
    void find(int x){
        printf("%d\n",a[first+x+1].mi!=INF?1:-1);
    }
};

int main(){
    scanf("%d%d",&n,&m);
    Segtree T;
    for(int i=1;i<=m;i++){
        int k,x;
        scanf("%d",&k);
        if(k!=3&&k!=4) scanf("%d",&x);
        if(k==1) T.insert(x);
        else if(k==2) T.erase(x);
        else if(k==3) T.querymin();
        else if(k==4) T.querymax();
        else if(k==5) T.getpre(x);
        else if(k==6) T.getsuc(x);
        else T.find(x);
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值