1. 程式人生 > >NOIP模擬賽(2017.9.15) -餐廳(restaurant)

NOIP模擬賽(2017.9.15) -餐廳(restaurant)

放下 輸入 機器 代碼 決定 -a scanf 實現 span

餐廳(restaurant)

【問題描述】

小R最近在玩一款模擬餐廳打工的遊戲,其中有一個疊盤子的小遊戲小R很喜歡。這個小遊戲是這樣的:有一個放盤子的機器會在一條直線上運動,機器裏裝著n個盤子,其中第i個盤子半徑為ri,並且如果要放下該盤子,盤子的中心必須放在直線上xi的位置上,小R可以決定放下哪些盤子和放下這些盤子的順序,盤子可以放在空位上,或者疊在一個上面沒有其他盤子的盤子上,但要求被疊的盤子必須包含要疊上去的盤子。小R想要讓疊出的盤子盡量高,請你計算出最高的一疊最多能疊幾個盤子。

【輸入格式】

第一行一個正整數n,表示盤子數。

接下來n行,每行兩個正整數ri和xi

【輸出格式】

輸出一個整數,表示答案。

【樣例輸入】

3

3 5

2 4

2 6

【樣例輸出】

2

【數據範圍】

對於20%的數據,n<=10;

對於50%的數據,n<=1,000;

對於100%的數據,n<=100,000,ri,xi<=109

【題解】

題目開始不太好理解,樣例解釋如圖(可以不按編號順序)

技術分享

對於滿足條件的堆疊方式,盤子的右端點一定是一個不下降序列,因此先按盤子的右端點排序。

對於左端點來說,同樣是一個不下降序列,因此對按右端點排序後的盤子的左端點求最長不下降子序列即可。

【代碼實現】

 1 #include<algorithm>
 2 #include<stdio.h>
 3 int n,r,x;
4 struct data{ 5 int l,r; 6 }p[100000]; 7 bool cmp(data a,data b){return a.r==b.r?a.l<b.l:a.r>b.r;} 8 int ans=0,best[100000]; 9 int bin(int num){ 10 int l=0,r=ans; 11 while(l<=r){ 12 int mid=(l+r)/2; 13 if(best[mid]==num){while(best[mid]==num)mid++;return mid;} 14 if
(best[mid]<num)l=mid+1; 15 if(best[mid]>num)r=mid-1; 16 } 17 return l; 18 } 19 int up(){ 20 best[0]=p[0].l; 21 for(int i=1;i<n;i++){ 22 if(p[i].l>=best[ans]){best[++ans]=p[i].l;continue;} 23 best[bin(p[i].l)]=p[i].l; 24 } 25 return ans+1; 26 } 27 int main(){ 28 freopen("restaurant.in","r",stdin); 29 freopen("restaurant.out","w",stdout); 30 scanf("%d",&n); 31 for(int i=0;i<n;i++){ 32 scanf("%d%d",&r,&x); 33 p[i].l=x-r,p[i].r=x+r; 34 } 35 std::sort(p,p+n,cmp); 36 printf("%d",up()); 37 return 0; 38 }

NOIP模擬賽(2017.9.15) -餐廳(restaurant)