Educational Codeforces Round 109 (Rated for Div. 2) C. Robot Collisions(思维分析题)

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

题目大意:在x轴上有n(1<=n<=3*10^5)个球,在坐标点0和坐标点m(2<=m<=10^8)处有一个挡板,每个球初始的时候位于整数坐标x_{i}(x_{i}<m),以及初始移动方向,向左或者向右,当球碰到挡板时会立马改变运动方向。每个1秒球移动1的距离,当两个球在同一个整数坐标点相遇时,两个球都会销毁。输出每个球的销毁时间,若球不会消失输出-1。

题解:

先分类讨论,各种情况下的相撞条件:

1,两个球相向而行,这时若两个球的距离为偶数,则两个球会相撞。奇数,则一定不会相撞。

2,两个球同向而行。由于两个球同向而行,所以在某一个球碰到挡板前,两个球之间的距离不会变化。当某个球碰到挡板时,那个球的方向瞬间发生变化,这时两个球相向而行。所以同向而行时,两个球的距离为偶数则会相撞,奇数则不会相撞。

3,两个球背向而行。在碰到挡板前,每秒两个球的距离+2,因此两个球在碰到挡板前距离的奇偶不会发生变化。若某一个球先碰到挡板,则变化为同向而行的情况。若同时碰到挡板,则变化为相向而行的情况。利用上面的两条结论,我们可以推导出,两个球背向而行相撞的条件也是偶数距离相撞,奇数距离则不会相撞。

所以总结下来,相距为偶数的球会相撞,相距为奇数的球一定不会相撞。

这个结论是解决本题的关键。

利用上面的结论,我们可以把球分为两个集合,初始在奇数坐标点的放到一个集合,初始在偶数坐标点的放到一个集合。同一个集合内的点之间一定会相撞,不同集合的点之间一定不会相撞。

所以我们也可以得出结论,最后最多只会剩下两个点。

接下来我们把目光放到一个集合,这个集合的点与点之间都是能相撞的,怎么计算这个集合的点的相撞时间?

我们假设有若干个球,它们的初始方向是 L R R L L L R R

我们容易观察到

第3个R一定会和第4个L相撞;

接下来第2个R一定会和第5个L相撞;

我们把容易确定会碰撞的球清除后,接下来就剩下LLRR,注意RL的情形一定会先相撞,所以最后一定会剩下若干个左边若干个L,右边若干个R。例如:LLLL...RRRR...

显然此时,同向的球之间会更先相撞。

具体来说对于R,最右边的两个R一定会相撞,剩余的R也会从右到左两两依次相撞;对于L,最左边的两个L会相撞,剩余的L也会从左到右两两依次相撞。

这样最后就可能剩下4种情况:一个不剩;只剩余一个L;只剩余一个R;剩余LR,此时这两个球一定会碰到一起。

因此,我们按照上述方法,先找出最容易确定会相撞的球RL,清除掉这些球后,再找后面的情况一定会相撞的球LL,RR,最后剩下LR。一步一步分析,我们可以准确求出每对相撞的球,根据每对相撞的球的初始距离,就可以计算出它们相撞的时间。

需要排序,所以复杂度O(nlogn)

解决本题的方法就是分类讨论,然后根据分析出的性质或者特点为突破口,把复杂的问题,分解为更小更清晰的问题。先找出问题中能确定的部分,再一步一步的分解和简化问题,最后解决问题。

代码如下:

#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;
}

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
"educational codeforces round 103 (rated for div. 2)"是一个Codeforces平台上的教育性比赛,专为2级选手设计评级。以下是有关该比赛的回答。 "educational codeforces round 103 (rated for div. 2)"是一场Codeforces平台上的教育性比赛。Codeforces是一个为程序员提供竞赛和评级的在线平台。这场比赛是专为2级选手设计的,这意味着它适合那些在算法和数据结构方面已经积累了一定经验的选手参与。 与其他Codeforces比赛一样,这场比赛将由多个问题组成,选手需要根据给定的问题描述和测试用例,编写程序来解决这些问题。比赛的时限通常有两到三个小时,选手需要在规定的时间内提交他们的解答。他们的程序将在Codeforces的在线评测系统上运行,并根据程序的正确性和效率进行评分。 该比赛被称为"educational",意味着比赛的目的是教育性的,而不是针对专业的竞争性。这种教育性比赛为选手提供了一个学习和提高他们编程技能的机会。即使选手没有在比赛中获得很高的排名,他们也可以从其他选手的解决方案中学习,并通过参与讨论获得更多的知识。 参加"educational codeforces round 103 (rated for div. 2)"对于2级选手来说是很有意义的。他们可以通过解决难度适中的问题来测试和巩固他们的算法和编程技巧。另外,这种比赛对于提高解决问题能力,锻炼思维和提高团队合作能力也是非常有帮助的。 总的来说,"educational codeforces round 103 (rated for div. 2)"是一场为2级选手设计的教育性比赛,旨在提高他们的编程技能和算法能力。参与这样的比赛可以为选手提供学习和进步的机会,同时也促进了编程社区的交流与合作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值