【问题描述】
想象一个机器人位于二维空间。初始时,机器人在(0,0)。有4个命令S,J,I,Z。具体的,如果机器人在(x,y),在收到S命令之后,移动到(x,y+1),收到J之后,移动到(x,y-1),I命令之后移动到(x+1,y),Z命令之后移动到(x-1,y)。在这个二维空间有n个固定的点,在每个命令之后,每个固定点会计算自己与机器人的曼哈顿距离,然后返回这些距离的总和。
PS:两个点(x1,y1)和(x2,y2)的曼哈顿|x1-x2|+|y1-y2|。
【输入格式】
第一行是正整数n和m。
接下来n行,每行两个整数,表示控制点的坐标,有些控制点坐标可能相同。
接下来一行,一个长度为m的字符串,表示机器人依次接受到的命令。
【输出格式】
输出m行,每行一个整数,第i行表示第i个命令执行以后所有控制点到机器人的曼哈顿距离之和。
【输入样例】
3 5
0 0
1 1
1 -1
SIJJZ
【输出样例】
5
4
3
4
5
【数据范围与约定】
对于40%的数据:n<=1000,m<=5000。
对于100%的数据:n <= 100000, m <= 300000。
(感觉这题很乱搞???)
【分析】
考虑机器人每走一步都以其为原点建立平面直角坐标系,先暴力每个点到机器人的曼哈顿距离之和。
然后预处理出
x
轴上下方、
记此时机器人的坐标为
(tx,ty)
,则当机器人向右走时,
y
轴以及
这里每一行每一列的固定点个数用的是
【代码】
#include <iostream>
#include <cstdio>
#include <map>
using namespace std;
typedef long long ll;
map<int, int> a, b;
const int N = 1e5 + 5;
char s[N * 3];
int lft, rig, upt, dwn, ex, ey, tx, ty, n, m;
ll Ans;
inline int Abs(const int &x)
{
return x < 0 ? -x : x;
}
inline int get()
{
char ch; int res = 0; bool f = false;
while (((ch = getchar()) < '0' || ch > '9') && ch != '-');
if (ch == '-') f = true;
else res = ch - '0';
while ((ch = getchar()) >= '0' && ch <= '9')
res = (res << 3) + (res << 1) + ch - '0';
return f ? -res : res;
}
inline void put(ll x)
{
if (x > 9) put(x / 10);
putchar(x % 10 + 48);
}
int main()
{
freopen("robot.in", "r", stdin);
freopen("robot.out", "w", stdout);
n = get(); m = get(); int u, v;
for (int i = 1; i <= n; ++i)
{
u = get(); v = get();
if (u < 0) lft++;
else if (u > 0) rig++;
else ey++;
if (v > 0) upt++;
else if (v < 0) dwn++;
else ex++;
Ans += Abs(u) + Abs(v);
a[u]++; b[v]++;
}
scanf("%s", s + 1);
for (int i = 1; i <= m; ++i)
{
switch(s[i])
{
case 'S': ty++;
Ans += dwn - upt + ex;
dwn += ex;
upt -= (ex = b[ty]);
break;
case 'J': ty--;
Ans += upt - dwn + ex;
upt += ex;
dwn -= (ex = b[ty]);
break;
case 'I': tx++;
Ans += lft - rig + ey;
lft += ey;
rig -= (ey = a[tx]);
break;
case 'Z': tx--;
Ans += rig - lft + ey;
rig += ey;
lft -= (ey = a[tx]);
break;
}
put(Ans), putchar('\n');
}
fclose(stdin); fclose(stdout);
return 0;
}