多校的时候这题写了一个多小时....调了半个多小时过完样例, 然后一直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);
}
}