题目链接:https://codeforces.com/contest/1525/problem/C

题目描述

给你一个数n代表机器人的数量,m代表边界,n个整数代表机器人的位置,n个字符代表机器人的运动方向,
每个机器人从时间0开始运动,一个时间单位移动一单位长度,机器人碰到边界会转向,只有两个机器人在 整数坐标 相撞时才会爆炸,问这些机器人在什么时间爆炸。

思路

首先,整数点才能相撞并爆炸,说明起点在奇数的坐标只能和起点在奇数的坐标相撞,起点在偶数的坐标只能和起点为偶数的坐标相撞,也就是说坐标奇偶性不同的两个机器人不能相撞。那我们应该将坐标进行分类讨论,不要忘了先将坐标点排序。那接下来呢?因为距离近的机器人会先相撞,距离远的会后相撞,这就跟括号匹配是一样的了,用一个栈去模拟括号匹配的过程,如果有剩下的元素,那栈里剩下来的元素一定是先LLLL...RRRRR这样的组合,L向左走撞上边界转向,所以从头到尾处理每一对的L,两两相撞,距离就是(L1的坐标+L2的坐标)/2,R从尾到头,同样算出距离。最后L最多剩下一个,R也最多剩下一个,如果L和R都有剩下的,就模拟两个坐标都转向再冲向彼此,算出距离即可


本来应该用函数去写,这样简单又简洁。

code

#include <bits/stdc++.h>
using namespace std;
#define mem(a, b) memset(a, b, sizeof(a))
#define ios ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
#define sc(x) scanf("%d", &(x))
#define pr(x) printf("%d ", (x))
//#define int long long
#define endl "\n"
inline int read() {
    int s = 0, w = 1;
    char ch = getchar();
    for (; !isdigit(ch); ch = getchar())
        if (ch == '-') w = -1;
    for (; isdigit(ch); ch = getchar()) s = (s << 1) + (s << 3) + (ch ^ 48);
    return s * w;
}
const long long N = 3e5 + 7;
struct z {
    int x;
    char c;
    int pos;
};
bool cmp(z aa, z bb) { return aa.x < bb.x; }
int t, n, len;
z a[N];
int timi[N];
z st1[N], st2[N];
int s1, s2;
int main() {
    t = read();
    while (t--) {
        mem(timi, -1);
        n = read(), len = read();
        for (int i = 1; i <= n; i++) sc(a[i]), a[i].pos = i;
        for (int i = 1; i <= n; i++) {
            scanf(" %c", &a[i].c);
        }
        sort(a + 1, a + 1 + n, cmp);
        s1 = 0, s2 = 0;
        mem(st1, 0), mem(st2, 0);
        for (int i = 1; i <= n; i++) {  //对奇数和偶数分别括号匹配
            if (a[i].x & 1) {
                if (s1 >= 1 && a[i].c == 'L' && st1[s1].c == 'R') {
                    int s = abs(st1[s1].x - a[i].x) / 2;
                    timi[st1[s1].pos] = s;
                    timi[a[i].pos] = s;
                    s1--;
                } else
                    st1[++s1] = {a[i].x, a[i].c, a[i].pos};
            } else {
                if (s2 >= 1 && a[i].c == 'L' && st2[s2].c == 'R') {
                    int s = abs(st2[s2].x - a[i].x) / 2;
                    timi[st2[s2].pos] = s;
                    timi[a[i].pos] = s;
                    s2--;
                } else
                    st2[++s2] = {a[i].x, a[i].c, a[i].pos};
            }
        }
        //奇数:
        int sum1 = 0;
        for (int i = 2; i <= s1; i += 2) {  //处理多余的‘L’
            if (st1[i].c == 'R') {
                sum1 = i - 1;
                break;
            }
            int s = (st1[i].x + st1[i - 1].x) / 2;
            timi[st1[i].pos] = s;
            timi[st1[i - 1].pos] = s;
        }
        if (st1[sum1].c == 'R') sum1--;
        for (int i = s1; i >= 2; i -= 2) {  //处理多余的‘R’
            if (st1[i - 1].c == 'L') break;
            int s = (2 * len - (st1[i].x + st1[i - 1].x)) / 2;
            timi[st1[i].pos] = s;
            timi[st1[i - 1].pos] = s;
        }
        if (sum1 % 2 == 1 &&
            (s1 - sum1) % 2 ==
                1) {  //如果处理完还剩下一个L和R则两个分别掉头相撞
            int s = (2 * len + st1[sum1].x - st1[sum1 + 1].x) / 2;
            timi[st1[sum1].pos] = s;
            timi[st1[sum1 + 1].pos] = s;
        }
        //偶数:
        sum1 = 0;
        for (int i = 2; i <= s2; i += 2) {
            if (st2[i].c == 'R') {
                sum1 = i - 1;
                break;
            }
            int s = (st2[i].x + st2[i - 1].x) / 2;
            timi[st2[i].pos] = s;
            timi[st2[i - 1].pos] = s;
        }
        if (st2[sum1].c == 'R') sum1--;
        for (int i = s2; i >= 2; i -= 2) {
            if (st2[i - 1].c == 'L') break;
            int s = (2 * len - (st2[i].x + st2[i - 1].x)) / 2;
            timi[st2[i].pos] = s;
            timi[st2[i - 1].pos] = s;
        }
        if (sum1 % 2 == 1 && (s2 - sum1) % 2 == 1) {
            int s = (2 * len + st2[sum1].x - st2[sum1 + 1].x) / 2;
            timi[st2[sum1].pos] = s;
            timi[st2[sum1 + 1].pos] = s;
        }
        for (int i = 1; i <= n; i++) pr(timi[i]);
        printf("\n");
    }
}