[日常训练] 距离之和

来源:互联网 发布:网络翻译英文 编辑:程序博客网 时间:2024/06/03 21:42

【问题描述】

想象一个机器人位于二维空间。初始时,机器人在(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 50 01 11 -1SIJJZ

【输出样例】

54345

【数据范围与约定】

对于40%的数据:n<=1000,m<=5000。对于100%的数据:n <= 100000, m <= 300000。

(感觉这题很乱搞???)

【分析】

考虑机器人每走一步都以其为原点建立平面直角坐标系,先暴力每个点到机器人的曼哈顿距离之和。
然后预处理出x轴上下方、y轴左右方、xy轴上以及每一行每一列的固定点个数。
记此时机器人的坐标为(tx,ty),则当机器人向右走时,y轴以及y轴左方的固定点到机器人的距离都增加1y轴右方的固定点到机器人的距离都减少1,同时现在y轴就变为y=tx+1y轴左方的固定点个数要加上原y轴的固定点个数,y轴右方的固定点个数要减去原y轴的固定点个数,现在y轴上的固定点个数可以通过之前每一行每一列的预处理更新。而当机器人向其它方向走时,也是同理。
这里每一行每一列的固定点个数用的是map存储,这样的总复杂度为O(mlogn)

【代码】

#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;}
原创粉丝点击