关闭

sicily 1802. Atomic Nucleus Investigation

标签: buildstructquery
497人阅读 评论(0) 收藏 举报
分类:

一系列操作,分别进行增加数据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;
}


 

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:624194次
    • 积分:4845
    • 等级:
    • 排名:第5898名
    • 原创:85篇
    • 转载:46篇
    • 译文:1篇
    • 评论:90条
    最新评论