一系列操作,分别进行增加数据M,移除数据M,查询两两之间的最小距离。( 1<=M<=100000)
建一棵1-100000的线段树,每个节点包含l, r, x, y , v,其中l,r分别表示左端点和右端点,x和y分别表示左子树的最大值(无数时为0)和右子树的最小值(无数时为Max),v表示改线段中最小的距离。给该数提供add,remove操作。 还必须添加一个数组vis来表示每个数是否在树中存在。
t[p].v =min( t[p].y -t[p].x , t[pl].v, t[pr].v )
#include <iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#define Max 100010
struct node
{
int l,r;
int x,y,v;
}tr[3*Max];
bool vis[Max];
int mx( int a, int b)
{
if( a==-1) return b;
if( b==-1) return a;
return a<b ? a:b;
}
void build(int a, int b, int p) //建树
{
tr[p].l =a; tr[p].r =b;
if( a==b)
return ;
int mid =(a+b)>>1;
build( a, mid, p<<1);
build( mid+1, b, (p<<1)+1);
}
void add( int p, int x) //添加数据
{
int mid =(tr[p].l +tr[p].r)>>1;
if( x<=mid)
{
if( tr[p].x< x) tr[p].x =x;
if( tr[p].l +1< tr[p].r ) add( p<<1, x);
}
else
{
if( tr[p].y>x) tr[p].y =x;
if( tr[p].l +1< tr[p].r ) add( (p<<1)+1, x);
}
//更新v值
int t1;
if( tr[p].x==0 || tr[p].y ==Max)
t1 =-1;
else
t1 =tr[p].y -tr[p].x;
if( tr[p].l +1== tr[p].r) //当该线段中只有两个元素时,其子结点的v值肯定都为-1,因此可以就此结束
{
tr[p].v =t1;
return ;
}
int t2 =mx(tr[p<<1].v, tr[(p<<1)+1].v);
tr[p].v =mx( t2, t1);
}
void remove( int p, int x) //移除数据
{
int mid =(tr[p].l +tr[p].r)>>1;
if( x<=mid)
{
if( x==tr[p].x)
{
int i;
for( i=x-1;i>=tr[p].l; i--)
if( vis[i])
{
tr[p].x =i; break;
}
if( x== tr[p].x)
tr[p].x =0;
}
if( tr[p].l+1 <tr[p].r) remove( p<<1, x);
}
else
{
if( x==tr[p].y)
{
int i;
for( i=x+1;i<=tr[p].r; i++)
if( vis[i] )
{
tr[p].y =i; break;
}
if( x== tr[p].y)
tr[p].y =Max;
}
if( tr[p].l+1 <tr[p].r) remove( (p<<1)+1, x);
}
//更新v值
int t1;
if( tr[p].x==0 || tr[p].y ==Max)
t1 =-1;
else
t1 =tr[p].y -tr[p].x;
if( tr[p].l +1== tr[p].r)
{
tr[p].v =t1;
return ;
}
int t2 =mx(tr[p<<1].v, tr[(p<<1)+1].v);
tr[p].v =mx( t2, t1);
}
void intil( int p)
{
tr[p].x= 0; tr[p].y =Max;
tr[p].v =-1;
//不知为什么这里一定要将所有结点都初始化
//开始我只初始化的线段树的各节点,结果输出的结果是错的
if( 2*p+1< 3*Max)
{
intil( p<<1);
intil( (p<<1)+1);
}
}
int main()
{
char s[20];
int t,n,m;
scanf("%d", &t);
build(1, 100000, 1);
int ca=0;
while( t--)
{
if( ca++) printf("\n");
scanf("%d", &n);
intil(1);
memset(vis, 0, sizeof( vis));
int i;
for( i=0; i<n; i++)
{
scanf("%s", s);
if( strcmp( s, "generate")==0 )
{
scanf("%d", &m);
if( !vis[m]) add(1, m);
vis[m] =1;
}
if( strcmp( s, "remove")==0 )
{
scanf("%d", &m);
if( vis[m]) remove(1, m);
vis[m] =0;
}
if( strcmp( s, "query") ==0)
printf("%d\n",tr[1].v);
}
}
return 0;
}