HDU 4302 Holedox Eating

多校的时候这题写了一个多小时....调了半个多小时过完样例, 然后一直wa.....

当时何其悲惨....其实也是很傻逼的一道, 就是模拟动物走的部分要写得仔细一点....尽量分模块写...


线段树: 单点更新, 区间查询, 维护区间离端点最近的有食物位置.

注意题目线段是0~n.


代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<string>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
inline int Rint() { int x; scanf("%d", &x); return x; }
inline int max(int x, int y) { return (x>y)? x: y; }
inline int min(int x, int y) { return (x<y)? x: y; }
#define FOR(i, a, b) for(int i=(a); i<=(b); i++)
#define FORD(i,a,b) for(int i=(a);i>=(b);i--)
#define REP(x) for(int i=0; i<(x); i++)
typedef long long int64;
#define INF (1<<30)
const double eps = 1e-8;
#define bug(s) cout<<#s<<"="<<s<<" "

//	开始小动物在0点, 0~L-1的线段, 会出现食物, 小动物想吃东西的时候找最近的地方去吃, 输出距离和
//	0~L-1 线段树, 单点更新, 区间查询, 维护区间两端点最近的食物位置, 跟每一点的食物数

#define MAXN 100002
int a[MAXN<<2], lidx[MAXN<<2], ridx[MAXN<<2];
int n;

void pushup(int e)
{
	//a[e] = a[e<<1]+a[e<<1|1];
	lidx[e] = lidx[e<<1];
	ridx[e] = ridx[e<<1|1];
	if(lidx[e]==-1) lidx[e] = lidx[e<<1|1];
	if(ridx[e]==-1) ridx[e] = ridx[e<<1];
}
void build(int l, int r,int e)
{
	a[e] =0;  lidx[e] = ridx[e] =-1;
	if(l==r) return;
	else
	{
		int mid =(l+r)>>1;
		build(l, mid, e<<1);
		build(mid+1, r, e<<1|1);
		pushup(e);
	}
}
void add(int p, int v, int l, int r,int e)
{
	if(l==r)
	{
		a[e] += v;
		if(a[e]) lidx[e] = ridx[e] = l;
		else lidx[e] = ridx[e] = -1;
		//bug(p);bug(a[e]);bug(lidx[e]);bug(ridx[e])<<endl;
	}
	else
	{
		int mid =(l+r)>>1;
		if(p<=mid)
			add(p, v, l, mid, e<<1);
		else
			add(p,v, mid+1, r,e<<1|1);
		pushup(e);
		//bug(l);bug(r);bug(a[e]);bug(lidx[e]);bug(ridx[e])<<endl;
	}
}
int lquery(int L, int R, int l, int r, int e)
{
	if(L<=l  && r<=R)
	{
		return lidx[e];
	}
	else
	{
		int mid=(l+r)>>1;
		int ret1 = -1;
		if(L<=mid)
			ret1 = lquery(L, R, l, mid, e<<1);
		int ret2 = -1;
		if(mid+1<=R)
			ret2 = lquery(L, R, mid+1, r, e<<1|1);
		if(ret1!=-1) return ret1;
		else  return ret2;
	}
}
int rquery(int L, int R, int l, int r, int e)
{
	if(L<=l && r<=R)
	{
		return ridx[e];
	}
	else
	{
		int mid = (l+r)>>1;
		int ret1= -1;
		if(L<=mid)
			ret1 = rquery(L, R, l, mid, e<<1);
		int ret2 = -1;
		if(mid+1<=R)
			ret2 = rquery(L, R, mid+1, r, e<<1|1);
		if(ret2!=-1) return ret2;
		else  return ret1;
	}
}

int dir;
int pos;	//动物位置
int move(int from, int to)		//from -> to	更新方向, 更新蛋糕, 返回距离
{
	int ret = abs(to-from);
	if(from!=to) dir = from>to;
	pos=to;
	add(to, -1, 0, n, 1);
	return ret;
}
int solve(int pos)		//	pos, 动物当前位置
{
	int left = rquery(0, pos, 0, n, 1);
	int right = lquery(pos, n, 0, n, 1);
	//bug(left);bug(right)<<endl;

	int goleft = -1;	//1往左, 0往右
	if(left == -1 && right!=-1)	//只能往右边
		goleft = 0;
	else if(right == -1 && left!=-1)		//只能往左边
		goleft = 1;
	else if(left ==-1 && right==-1)	//没蛋糕
		goleft = -1;
	else	//两边都有蛋糕
	{
		int toleft = pos-left;
		int toright = right-pos;
		if(toleft!=toright)
			goleft = toleft<toright;
		else
			goleft = dir;
	}

	if(goleft == -1) return 0;		//没蛋糕的时候
	else if(goleft) return move(pos, left);
	else  return move(pos, right);
}

int main()
{
	int T = Rint();
	FOR(tt, 1, T)
	{
		int ret = 0;
		dir = 0;		//右边
		pos = 0;
		n = Rint();	int q = Rint();
		build(0, n, 1);		//傻逼了忘调用build看半小时.....
		REP(q)
		{
			int op =Rint();
			if(op)
			{
				ret+=solve(pos);
				//bug(ret)<<endl;
			}
			else
			{
				int x =Rint();				//0 x(0<=x<=L, x is a integer)    0~n 啊 ...不是n-1....原来比赛的时候是这里一直wa...
				add(x, 1, 0, n, 1);
			}
		}
		printf("Case %d: %d\n", tt, ret);
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值