题目链接:https://codeforces.com/contest/1525/problem/C
题目大意:在轴上有
个球,在坐标点0和坐标点
处有一个挡板,每个球初始的时候位于整数坐标
,以及初始移动方向,向左或者向右,当球碰到挡板时会立马改变运动方向。每个1秒球移动1的距离,当两个球在同一个整数坐标点相遇时,两个球都会销毁。输出每个球的销毁时间,若球不会消失输出-1。
题解:
先分类讨论,各种情况下的相撞条件:
1,两个球相向而行,这时若两个球的距离为偶数,则两个球会相撞。奇数,则一定不会相撞。
2,两个球同向而行。由于两个球同向而行,所以在某一个球碰到挡板前,两个球之间的距离不会变化。当某个球碰到挡板时,那个球的方向瞬间发生变化,这时两个球相向而行。所以同向而行时,两个球的距离为偶数则会相撞,奇数则不会相撞。
3,两个球背向而行。在碰到挡板前,每秒两个球的距离+2,因此两个球在碰到挡板前距离的奇偶不会发生变化。若某一个球先碰到挡板,则变化为同向而行的情况。若同时碰到挡板,则变化为相向而行的情况。利用上面的两条结论,我们可以推导出,两个球背向而行相撞的条件也是偶数距离相撞,奇数距离则不会相撞。
所以总结下来,相距为偶数的球会相撞,相距为奇数的球一定不会相撞。
这个结论是解决本题的关键。
利用上面的结论,我们可以把球分为两个集合,初始在奇数坐标点的放到一个集合,初始在偶数坐标点的放到一个集合。同一个集合内的点之间一定会相撞,不同集合的点之间一定不会相撞。
所以我们也可以得出结论,最后最多只会剩下两个点。
接下来我们把目光放到一个集合,这个集合的点与点之间都是能相撞的,怎么计算这个集合的点的相撞时间?
我们假设有若干个球,它们的初始方向是
我们容易观察到
第3个R一定会和第4个L相撞;
接下来第2个R一定会和第5个L相撞;
我们把容易确定会碰撞的球清除后,接下来就剩下,注意
的情形一定会先相撞,所以最后一定会剩下若干个左边若干个
,右边若干个
。例如:
显然此时,同向的球之间会更先相撞。
具体来说对于,最右边的两个
一定会相撞,剩余的
也会从右到左两两依次相撞;对于
,最左边的两个
会相撞,剩余的
也会从左到右两两依次相撞。
这样最后就可能剩下4种情况:一个不剩;只剩余一个;只剩余一个
;剩余
,此时这两个球一定会碰到一起。
因此,我们按照上述方法,先找出最容易确定会相撞的球,清除掉这些球后,再找后面的情况一定会相撞的球
,最后剩下
。一步一步分析,我们可以准确求出每对相撞的球,根据每对相撞的球的初始距离,就可以计算出它们相撞的时间。
需要排序,所以复杂度
解决本题的方法就是分类讨论,然后根据分析出的性质或者特点为突破口,把复杂的问题,分解为更小更清晰的问题。先找出问题中能确定的部分,再一步一步的分解和简化问题,最后解决问题。
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int nn =310000;
const int inff = 0x3fffffff;
const double eps = 1e-8;
typedef long long LL;
const double pi = acos(-1.0);
const LL mod = 1000000007;
int n,m;
string dir[nn];
int ans[nn];
int main()
{
int t;
cin>>t;
while(t--)
{
vector<pair<int,int> >ve[2];
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
ve[x%2].push_back(make_pair(x,i));
ans[i]=-1;
}
for(int i=1;i<=n;i++)
{
cin>>dir[i];
}
if(ve[0].size())
sort(ve[0].begin(),ve[0].end());
if(ve[1].size())
sort(ve[1].begin(),ve[1].end());
for(int k=0;k<2;k++)
{
stack<int>sta;
for(int i=0;i<ve[k].size();i++)
{
int id=ve[k][i].second;
if(dir[id]=="R")
sta.push(i);
else {
if(sta.size())
{
int u=sta.top();
sta.pop();
int dis=ve[k][i].first-ve[k][u].first;
ans[id]=ans[ve[k][u].second]=dis/2;
}
}
}
}
for(int k=0;k<2;k++)
{
stack<int>l;
int num=ve[k].size();
for(int i=0;i<num;i++)
{
int id=ve[k][i].second;
if(ans[id]!=-1)
continue;
if(dir[id]=="L")
{
if(l.empty())
l.push(i);
else {
int u=l.top();
l.pop();
ans[id]=ans[ve[k][u].second]=ve[k][u].first+(ve[k][i].first-ve[k][u].first)/2;
}
}
}
stack<int>r;
for(int i=num-1;i>=0;i--)
{
int id=ve[k][i].second;
if(ans[id]!=-1)
continue;
if(dir[id]=="R")
{
if(r.empty())
r.push(i);
else {
int u=r.top();
r.pop();
ans[id]=ans[ve[k][u].second]=(ve[k][u].first-ve[k][i].first)/2+m-ve[k][u].first;;
}
}
}
if(l.size()&&r.size())
{
int u=l.top();
l.pop();
int v=r.top();
r.pop();
int ti=0;
if(ve[k][u].first<=m-ve[k][v].first)
{
ti+=ve[k][u].first;
int x=0,y=ve[k][v].first+ve[k][u].first;
ti+=m-y;
x+=m-y,y=m;
ti+=(y-x)/2;
} else {
ti+=m-ve[k][v].first;
int x=ve[k][u].first-(m-ve[k][v].first),y=m;
ti+=x;
y-=x;
x=0;
ti+=(y-x)/2;
}
ans[ve[k][u].second]=ans[ve[k][v].second]=ti;
}
}
for(int i=1;i<=n;i++)
{
printf("%d%c",ans[i],i==n?'\n':' ');
}
}
return 0;
}