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