【CQBZOJ 2856】[线段树]原子核研究

题目描述

线段树水题专项赛:Portal
要求一种数据结构使得能够支持插入一个值,删除一个值,查询最小的差值。(所有输入数据小于100000,并且你需要自动去重)

题目解析

一看,这不一思博线段树吗?维护每一个区间左右有多少空格,中间(不包含左右端点)的最短区间,然后两两合并就行了啊。
于是迅速码完代码,信心满满的交了,然后就爆成了0分。
考完检查,mdzz,数组没清零,mdzz,build的区间用的(1,n)。
我天,以后一定要记住,多组数据一定记得清零,线段树先找好区间,不要手残乱打。

代码

#include<iostream>
#include<cstring>
#include<cstdio>
#include<set>
#include<algorithm>
using namespace std;

#define MAXN 100000
#define MAXM 100000
#define INF 0x3f3f3f3f
typedef long long int LL;

template<class T>
void Read(T &x){
    x=0;char c=getchar();bool flag=0;
    while(c<'0'||'9'<c){if(c=='-')flag=1;c=getchar();}
    while('0'<=c&&c<='9'){x=x*10+c-'0';c=getchar();}
    if(flag)x=-x;
}

int L[MAXM*3],R[MAXM*3];
int len[MAXM*3];
int lval[MAXM*3],rval[MAXM*3],minval[MAXM*3];
int sz;

void updata(int x){
    lval[x]=lval[x<<1];
    if(lval[x<<1]==len[x<<1])lval[x]+=lval[x<<1|1];
    rval[x]=rval[x<<1|1];
    if(rval[x<<1|1]==len[x<<1|1])rval[x]+=rval[x<<1];

    minval[x]=min(minval[x<<1],minval[x<<1|1]);
    if(rval[x<<1]!=len[x<<1]&&lval[x<<1|1]!=len[x<<1|1])
        minval[x]=min(minval[x],rval[x<<1]+lval[x<<1|1]);
}

void build(int l,int r,int x){
    L[x]=l,R[x]=r;
    len[x]=r-l+1;
    lval[x]=rval[x]=len[x];
    minval[x]=INF;

    if(L[x]==R[x])return;

    int mid=(l+r)>>1;
    build(l,mid,x<<1);
    build(mid+1,r,x<<1|1);
    updata(x);
}

void insert(int pos,int x){
    if(L[x]==R[x]){
        lval[x]=rval[x]=0;
        minval[x]=INF;
        return;
    }

    int mid=(L[x]+R[x])>>1;
    if(pos<=mid)insert(pos,x<<1);
    else insert(pos,x<<1|1);
    updata(x);
}

void del(int pos,int x){
    if(L[x]==R[x]){
        lval[x]=rval[x]=1;
        minval[x]=INF;
        return;
    }

    int mid=(L[x]+R[x])>>1;
    if(pos<=mid)del(pos,x<<1);
    else del(pos,x<<1|1);
    updata(x);
}

int query(){
    if(sz<2)return -1;
    else return minval[1]+1;
}

bool has[MAXM+10];

int main(){
    //freopen("data2.in","r",stdin);
    //freopen("atomic.out","w",stdout);

    int T,n;
    Read(T);

    while(T--){
        Read(n);

        sz=0;
        build(1,MAXM,1);
        memset(has,0,sizeof(has));

        char str[10];
        int x;
        for(int i=1;i<=n;++i){
            scanf("%s",str);
            if(str[0]=='g'){
                Read(x);
                if(!has[x]){
                    has[x]=1,++sz;
                    insert(x,1);
                }
            }
            else if(str[0]=='r'){
                Read(x);
                if(has[x]){
                    has[x]=0,--sz;
                    del(x,1);
                }
            }
            else
                printf("%d\n",query());
        }

        putchar('\n');
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值