题目大意
在一条数轴上有
n
n
n 个机器人,每个机器人有一个初始的朝向,之后每一秒,它会向着它朝向的方向走一个单位,如果到达了
0
0
0 或者
m
m
m 那么就会立即掉头。如果多个机器人在同一整数点相遇,那么它们就会碰撞炸掉,在此之后就不会与其他机器人碰撞了。现需要你求出每个机器人最早在第几时刻炸掉,如果不会,则输出 -1
。
Solution
首先是注意一点:当且仅当两个机器人奇偶性相同时才会相撞,并且没有意外是一定会相撞的。
可以很简单地证一下,每一次移动每一个机器人的位置奇偶性都会改变,如果两个机器人的奇偶性不同,那么任意时刻其奇偶性都是不同的,也就不可能同时在一个整数点相遇了。
所以我们可以对每个点进行奇偶分类。
然后对于每组,我们考虑机器人相撞,可以发现如果两个机器人是相对的并且中间没有其他机器人,那么必定是这两个机器人相撞……等等,这不就是括号匹配么。所以用一个栈维护一下就可以把所有相对的机器人处理掉,最后只剩下:L...LR...R
这样的朝向,此时,我们对两边分别进行处理,对于向左的,最左边转向后必定和左边第二个相撞,左边第三个必定转向后和左边第四个相撞……右边也是同理。
这样处理完后,可能会剩下
1
1
1 个或者
2
2
2 个机器人,如果是
1
1
1 个,那么没有人与之相撞,则答案为 -1
,否则,剩下
2
2
2 个朝向是这样的:LR
,让它们两个走到头再转向回来相撞即可。
Code
#include<bits/stdc++.h>
#define ll long long
#define inf 1<<30
#define int long long
using namespace std;
const int MAXN=3e5+10;
struct node{
int pos,id;
char dir;
node(){}
node(int _pos,int _id,char _dir){
pos=_pos;id=_id;dir=_dir;
}
bool friend operator<(node a,node b){
return a.pos<b.pos;
}
}odd[MAXN],eve[MAXN],bas[MAXN];
int stk[MAXN],top,ans[MAXN];
int bin[MAXN],hed;
void solve(){
int n,m,ocnt=0,ecnt=0;
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++)
scanf("%lld",&bas[i].pos),bas[i].id=i;
for(int i=1;i<=n;i++)
scanf(" %c",&bas[i].dir);
sort(bas+1,bas+1+n);//记得排序
for(int i=1;i<=n;i++){
if(bas[i].pos&1) odd[++ocnt]=bas[i];
else eve[++ecnt]=bas[i];
}//奇偶分组
top=0;hed=0;
for(int i=1;i<=ocnt;i++){
if(odd[i].dir=='R') stk[++top]=i;
else{
if(!top) bin[++hed]=i;//如果栈空,说明这个向左的是多出来的,存着就行
else{
int j=stk[top--];
ans[odd[i].id]=ans[odd[j].id]=(odd[i].pos-odd[j].pos)/2;
}
}
}//做括号匹配,把相对的消去,变成 L...LR...R 的形式
for(int i=1;i<hed;i+=2){
ans[odd[bin[i]].id]=ans[odd[bin[i+1]].id]=(odd[bin[i+1]].pos-odd[bin[i]].pos)/2+odd[bin[i]].pos;
}//处理向左多出来的部分,两两相撞
for(int i=top;i>1;i-=2){
ans[odd[stk[i]].id]=ans[odd[stk[i-1]].id]=(odd[stk[i]].pos-odd[stk[i-1]].pos)/2+m-odd[stk[i]].pos;
}//stk 中多出来的就是向右多余的,也是一样处理
if(hed%2&&top%2){//如果两个都有 1 个剩余,那么把它们继续撞
ans[odd[bin[hed]].id]=ans[odd[stk[1]].id]=(odd[bin[hed]].pos+m-odd[stk[1]].pos+m)/2;
}else if(hed%2) ans[odd[bin[hed]].id]=-1;
else if(top%2) ans[odd[stk[1]].id]=-1;//否则答案就是 -1
/* 处理奇数 */
top=0;hed=0;
for(int i=1;i<=ecnt;i++){
if(eve[i].dir=='R') stk[++top]=i;
else{
if(!top) bin[++hed]=i;
else{
int j=stk[top--];
ans[eve[i].id]=ans[eve[j].id]=(eve[i].pos-eve[j].pos)/2;
}
}
}
for(int i=1;i<hed;i+=2){
ans[eve[bin[i]].id]=ans[eve[bin[i+1]].id]=(eve[bin[i+1]].pos-eve[bin[i]].pos)/2+eve[bin[i]].pos;
}for(int i=top;i>1;i-=2){
ans[eve[stk[i]].id]=ans[eve[stk[i-1]].id]=(eve[stk[i]].pos-eve[stk[i-1]].pos)/2+m-eve[stk[i]].pos;
}if(hed%2&&top%2){
ans[eve[bin[hed]].id]=ans[eve[stk[1]].id]=(eve[bin[hed]].pos+m-eve[stk[1]].pos+m)/2;
}else if(hed%2) ans[eve[bin[hed]].id]=-1;
else if(top%2) ans[eve[stk[1]].id]=-1;
//和奇数完全一样
/* 处理偶数 */
for(int i=1;i<=n;i++)
printf("%lld ",ans[i]);
printf("\n");
}
signed main()
{
int T;
for(scanf("%lld",&T);T--;)
solve();
}