AtCoder Grand Contest 023 D GO Home

传送门

一道很有意思的题

大意:有在一条数轴上有N座公寓,第 i 座公寓坐落于上 x i 上,公司坐落于S,公司的每个员工都住在某个公寓里,第 i 个公寓里住了 p i 个人;每天下班的时候大家⼀起投票向前还是向后,每个都能知道大家的得票情况,并根据大家的投票情况来选择自己的投票情况,如果票数相同就固定向前走,但最重要的一点,每个⼈是自私的,希望自己尽早回家。 ,但不一定就会投自己方向(可以参考传送门的样例)每个人到家了就会下车,问大家做最优决策的情况下,最后⼀个回家的人多久就可以到家?

这道题主要就是看思维

像样例1那样
坐落于3的4个小朋友肯定会投右边,1的三个小盆友也绝对会投左边,那么问题来了,4的那两个小朋友,他们会考虑到两种情况,左还是右,但他们会投左边,因为左边的人是比他们多的,所以当3的4个人下了后,无论如何车都还是会向左走的,所以对他们来说,与其先走过来在走远再走过来,不如直接向左,再向右,可以发现这样是更优的

所以我们发现
每个地方的人的决策是根据所有人的决策而定的,每个人会根据在自己向公司方向的前一个地方的人时,投左右两边的人的数量来决定,如果自己方向的人更多的话就投自己这边,否则就投反方向,也就是说每个人的决策是需要根据全局决策而定的,朴素算法复杂度O( n 2 ) 会超时

所以我们考虑换一种方法
我们从最后一个人的时候开始往前推,则每个人的决策能直接根据前面已有的状态得出结论,如果一个地方自己方向的人加上自己这人的人小于对面的人,那么对面的人数就加上自己这儿的人,否则就是自己这边的人数增加,复杂度O(n);

代码如下

#include<bits/stdc++.h>
using namespace std;
long long n,s,a[1000005],p[1000005];
inline long long read()                         
{

    char ch;
    while((ch=getchar())<'0'||ch>'9'){;}
    long long res=ch-'0';
    while((ch=getchar())>='0'&&ch<='9')
    res=res*10+ch-'0';
    return res;
}
int main()
{
    n=read(),s=read();
    for(long long i=1;i<=n;i++)
    {
        a[i]=read(),p[i]=read();
    }
    long long l=1,r=n;
    long long ans=0;
    while(l<=r)
    {
        if(a[l]>=s)
        {
            ans+=a[r]-s;
            break;
        }
        if(a[r]<=s)
        {
            ans+=s-a[l];
            break;
        }
        ans+=a[r]-a[l];
        if(p[l]>=p[r])
        {
            while(p[l]>=p[r]&&l<r)
            {
                p[l]+=p[r];
                r=r-1;
            }   
        }
        else 
        {
            while(p[r]>p[l]&&l<r)
            {
                p[r]+=p[l];
                l+=1;
            }
        }
    }
    cout<<ans<<endl;
    return 0;
} 

猜你喜欢

转载自blog.csdn.net/qq_42555009/article/details/81390052