一道很有意思的题
大意:有在一条数轴上有N座公寓,第ii座公寓坐落于上xixi上,公司坐落于S,公司的每个员工都住在某个公寓里,第ii个公寓里住了pipi个人;每天下班的时候大家⼀起投票向前还是向后,每个都能知道大家的得票情况,并根据大家的投票情况来选择自己的投票情况,如果票数相同就固定向前走,但最重要的一点,每个⼈是自私的,希望自己尽早回家。 ,但不一定就会投自己方向(可以参考传送门的样例)每个人到家了就会下车,问大家做最优决策的情况下,最后⼀个回家的人多久就可以到家?
这道题主要就是看思维
像样例1那样
坐落于3的4个小朋友肯定会投右边,1的三个小盆友也绝对会投左边,那么问题来了,4的那两个小朋友,他们会考虑到两种情况,左还是右,但他们会投左边,因为左边的人是比他们多的,所以当3的4个人下了后,无论如何车都还是会向左走的,所以对他们来说,与其先走过来在走远再走过来,不如直接向左,再向右,可以发现这样是更优的
所以我们发现
每个地方的人的决策是根据所有人的决策而定的,每个人会根据在自己向公司方向的前一个地方的人时,投左右两边的人的数量来决定,如果自己方向的人更多的话就投自己这边,否则就投反方向,也就是说每个人的决策是需要根据全局决策而定的,朴素算法复杂度O(n2n2) 会超时
所以我们考虑换一种方法
我们从最后一个人的时候开始往前推,则每个人的决策能直接根据前面已有的状态得出结论,如果一个地方自己方向的人加上自己这人的人小于对面的人,那么对面的人数就加上自己这儿的人,否则就是自己这边的人数增加,复杂度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;
}