2012 Multi-University Training Contest 1 Holedox Eating(线段树)

用线段树保存当前区间里最近的蛋糕位置。

几个细节值得注意:1、每次吃完蛋糕后要更新当前所在位置和前一个吃蛋糕的位置,以便在遇到有多个蛋糕距离一样的时候选择按原来方向吃一个蛋糕。

                                    2、一个点可能有多个蛋糕,所以每次吃一个点的蛋糕后,该点蛋糕数减1,如果蛋糕数为0,则把该点值设为INF,否则该点值不变。

#include <stdio.h>
#include <string.h>
#define maxn 100050
#define lson l , m , rt *2 
#define rson m+1 , r , rt *2 +1
#define dem int m = (l + r) / 2
#define inf 999999999
int site[maxn*4];
int num[maxn*4];
int n,m;
int now,pre;
int min(int x,int y)
{
	return x<y?x:y;	
}
int abs(int x)
{
	return x<0?0-x:x;	
}
void PushUp(int rt)
{
	if(abs(site[rt*2]-now)==abs(site[rt*2+1]-now))
	{
		if(pre<now)
			site[rt]=site[rt*2+1];
		else
			site[rt]=site[rt*2];	
	}	
	else
		site[rt]=abs(site[rt*2]-now) < abs(site[rt*2+1]-now) ? site[rt*2] : site[rt*2+1];
}
void build(int l,int r,int rt)
{
	site[rt]=inf;
	if(l==r)	return ;
	int m=(l+r)/2;
	build(lson);
	build(rson);
}
void update(int index,int value,int l,int r,int rt,int op)
{
	if(l==r)
	{
		if(op==1)
			num[rt]++;
		else
			num[rt]--;
		if(num[rt]==0) site[rt]=inf;
		else	site[rt]=value;
		return ;	
	}	
	int m=(l+r)/2;
	if(index<=m) update(index,value,lson,op);
	else	update(index,value,rson,op);
	PushUp(rt);
}
int main()
{
	   freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
	int T,ncase,a,b,i;
	scanf("%d",&T);
	ncase=1;
	while(T--)
	{
		printf("Case %d: ",ncase++);	
		scanf("%d%d",&n,&m);
		now=0;
		pre=0;
		memset(num,0,sizeof(num));
		build(0,n,1);
	
		int ans=0;
		for(i=1;i<=m;i++)
		{
			scanf("%d",&a);
			
			if(a==0){
				scanf("%d",&b);
				update(b,b,0,n,1,1);		
			}
			else{
				if(site[1]==inf)
					continue;
				ans+=abs(site[1]-now);
				pre=now;
				now=site[1];
				update(now,now,0,n,1,0);
			}
		}
		printf("%d\n",ans);
	}	
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值