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

BZOJ_3685_普通van Emde Boas树_权值线段树

时间:2018-05-06 16:19:47      阅读:188      评论:0      收藏:0      [点我收藏+]

标签:ati   线段树   nbsp   pre   using   int   sample   rip   线段   

BZOJ_3685_普通van Emde Boas树_权值线段树

Description

设计数据结构支持:
1 x  若x不存在,插入x
2 x  若x存在,删除x
3    输出当前最小值,若不存在输出-1
4    输出当前最大值,若不存在输出-1
5 x  输出x的前驱,若不存在输出-1
6 x  输出x的后继,若不存在输出-1
7 x  若x存在,输出1,否则输出-1

Input

第一行给出n,m 表示出现数的范围和操作个数
接下来m行给出操作
n<=10^6,m<=2*10^6,0<=x<n

Output

Sample Input

10 11
1 1
1 2
1 3
7 1
7 4
2 1
3
2 3
4
5 3
6 2

Sample Output

1
-1
2
2
2
-1


 

权值线段树写的,感觉不是很慢。

唯一需要注意的是56操作时给出的x可能小于最小值/最大值,这时需要输出-1。

 

代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 1000050
#define ls p<<1
#define rs p<<1|1
#define maxn (n-1)
inline char nc() {
    static char buf[100000],*p1,*p2;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int rd() {
    register int x=0; register char s=nc();
    while(s<‘0‘||s>‘9‘) s=nc();
    while(s>=‘0‘&&s<=‘9‘) x=(x<<3)+(x<<1)+s-‘0‘,s=nc();
    return x;
}
int t[N<<2],n,m,now;
void insert(int l,int r,int x,int v,int p) {
    if(l==r) {
        if(v==0) {
            if(t[p]==0) now++;
            t[p]=1;
        }else {
            if(t[p]==1) now--;
            t[p]=0;
        }
        return ;
    }
    int mid=(l+r)>>1;
    if(x<=mid) insert(l,mid,x,v,ls);
    else insert(mid+1,r,x,v,rs);
    t[p]=t[ls]+t[rs];
}
int get_rank(int l,int r,int x,int p) {
    if(l==r) return 1;
    int mid=(l+r)>>1;
    if(x<=mid) return get_rank(l,mid,x,ls);
    else return get_rank(mid+1,r,x,rs)+t[ls];
}
int get_x(int l,int r,int k,int p) {
    if(l==r) return l;
    int mid=(l+r)>>1;
    if(k<=t[ls]) return get_x(l,mid,k,ls);
    else return get_x(mid+1,r,k-t[ls],rs);
}
int calcmin(int l,int r,int p) {
    if(l==r) return l;
    int mid=(l+r)>>1;
    if(t[ls]) return calcmin(l,mid,ls);
    else return calcmin(mid+1,r,rs);
}
int calcmax(int l,int r,int p) {
    if(l==r) return l;
    int mid=(l+r)>>1;
    if(t[rs]) return calcmax(mid+1,r,rs);
    else return calcmax(l,mid,ls);
}
int exist(int l,int r,int x,int p) {
    if(l==r) return t[p]?1:-1;
    int mid=(l+r)>>1;
    if(x<=mid) return exist(l,mid,x,ls);
    else return exist(mid+1,r,x,rs);
}
int main() {
    n=rd(); m=rd();
    int i,x,opt;
    for(i=1;i<=m;i++) {
        opt=rd();
        if(opt!=3&&opt!=4) x=rd(); 
        if(opt==1) {
            insert(0,maxn,x,0,1);
        }else if(opt==2) {
            insert(0,maxn,x,1,1);
        }else if(opt==3) {
            printf("%d\n",now?calcmin(0,maxn,1):-1);
        }else if(opt==4) {
            printf("%d\n",now?calcmax(0,maxn,1):-1);
        }else if(opt==5) {
            if(x<=calcmin(0,maxn,1)) puts("-1");
            else {
                int k=get_rank(0,maxn,x,1)-1;
                printf("%d\n",get_x(0,maxn,k,1));
            }
        }else if(opt==6) {
            if(x>=calcmax(0,maxn,1)) puts("-1");
            else {
                int k=get_rank(0,maxn,x+1,1);
                printf("%d\n",get_x(0,maxn,k,1));
            }
        }else {
            printf("%d\n",exist(0,maxn,x,1));
        }
    }
}

 

BZOJ_3685_普通van Emde Boas树_权值线段树

标签:ati   线段树   nbsp   pre   using   int   sample   rip   线段   

原文地址:https://www.cnblogs.com/suika/p/8998108.html

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