題意
現在有一個數軸,有n個公寓。然後第i個公寓在xi位置上,且當前第i個公寓住pi個人。那麼現在我們從s開始出發。然後就會民主投票(多數人暴政),會選擇當前車子往左往右走一格,若票數相同就走左。當然每個人都是自私的且非常聰明的(這並不意味這他會一定往自己家走)。問最早什麼時候送完所有人。
前言
其實這題是我無聊找atcoder題時找到的。
當時想了想感覺沒思路,後來才發現奇妙無比。
題解
首先我們分析一下這些自私的人會怎麼選。
假設當前只剩下最左邊和最右邊的兩家公寓。
如果最左邊的公寓人數大於最右邊的人數,那麼最右邊的人數最聰明的做法是把全票投給最左邊的人。
爲什麼呢?
假設有這麼個數據:
4 10
1 10
12 5
13 5
14 5
你可能會想說最右邊的三個公寓齊心協力來對抗左邊的一個公寓。
然鵝當車子往右邊走的時候,人數會逐漸減少,反而讓最左邊的公寓佔了上風。
然後就往右邊走了一段不必要的路程。
感覺這個謙讓的思維很像“海盜分金問題”。
然後我們就一直把右邊的人投票投進去左邊的人,直到出現一個右邊的人大於左邊的人。
然後這樣週而復始。
當起點左邊或右邊沒有人反抗了之後,就可以停止了。
好一道思維神題。
代碼
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
const int maxn=1000010;
int n;
long long st,ans,x[maxn],y[maxn];
int main()
{
scanf("%d%lld",&n,&st);
for (int i=1;i<=n;i++)
{
scanf("%lld%lld",&x[i],&y[i]);
}
int l=1;
int r=n;
while (l<=r)
{
if (x[l]>=st)
{
ans=ans+x[r]-st;
break;
}
if (x[r]<=st)
{
ans=ans+st-x[l];
break;
}
ans=ans+x[r]-x[l];
if (y[l]>=y[r])
{
while (y[l]>=y[r] && l<r)
{
y[l]=y[l]+y[r];
r--;
}
}
else
{
while (y[l]<y[r] && l<r)
{
y[r]=y[r]+y[l];
l++;
}
}
}
printf("%lld\n",ans);
}