1. 程式人生 > >小明搬家_NOI導刊2010提高(05)

小明搬家_NOI導刊2010提高(05)

span long i++ 高效 效率 algorithm using 分鐘 %d

題目描述

小明要搬家了,大家都來幫忙。

小明現在住在第N樓,總共K個人要把X個大箱子搬上N樓。

最開始X個箱子都在1樓,但是經過一段混亂的搬運已經亂掉了。最後大家發現這樣混亂地搬運過程效率太低了,於是總結出了提高效率的方法。

大家的速度都是每分鐘上(或下)一層樓。所有向上走的人手中都拿一個箱子,所有向下走的人手中都不拿箱子。到達第N層立刻放下箱子向下走,到達第1層立刻拿起箱子向上走。當一個人向上走,另一人向下走而在樓道裏相遇時,向上走的人將手中的箱子交給另一人,兩人同時反向。即原來拿箱子向上走的人不拿箱子向下走,原來不拿箱子向下走的人現拿著箱子向上走。

求將所有箱子搬完所需的最短時間。

輸入輸出格式

輸入格式:

第一行N(N≤10^9),K(K≤500000),M(M≤10^9),分別表示樓層數、人數、還放在一樓地上的箱子數。

接下來K行,每行兩個數Ai,Bi。

Ai表示第i人現所在的樓層數,Bi為0或1,為0表示第i人正拿著箱子向上走,為1表示第i人不拿箱子向下走。

輸入滿足沒有任意兩人正在同一樓層,在第1層的人一定正拿著箱子向上走,在第N層的人一定正不拿箱子向下走。

輸出格式:

僅包含一個整數,為搬完箱子的時間。

輸入輸出樣例

輸入樣例#1:
5 2 4
1 0
3 0
輸出樣例#1:
20

說明

對於30%的數據有K≤100,M≤100;

對於60%的數據有K≤1000,M≤l09;

對於l000/o的數據有K≤500000,M≤109。

這道題分析時可以忽略“當一個人向上走,另一人向下走而在樓道裏相遇時,向上走的人將手中的箱子交給另一人,兩人同時反向”這句話,因為想想就知道換了和沒換其實差不多

跟藍皮書上的一道叫什麽螞蟻的題想法很像

分析時先假設所有人都一起搬了整數趟回到原來位置,然後若剛好搬完則把這些時間加上所有人中距樓頂所需時間最大的人的時間(向下時時間為負數),沒有正好搬完則從最小時間開始依次再加一趟,然後再取最長的時間

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4
#include<algorithm> 5 using namespace std; 6 int s[500001],cnt; 7 long long n,k,m; 8 int main() 9 {int i,a,b; 10 cin>>n>>k>>m; 11 for (i=1;i<=k;i++) 12 { 13 scanf("%d%d",&a,&b); 14 if (b==0) s[++cnt]=n-a; 15 else s[++cnt]=a-n; 16 } 17 sort(s+1,s+k+1); 18 s[0]=s[k]; 19 cout<<(m/k)*(n-1)*2+s[m%k]; 20 }

小明搬家_NOI導刊2010提高(05)