為了表示方便,設x−petya和vasya被聘為快遞員。在工作日期間,他們將提供包裹到線上的不同點。根據公司的內部規定,包裹的交付必須嚴格按照一定的順序進行。最初,petya處於座標s1的點,vasya位於座標s2的點,n個顧客所需訪問的順序位於點x1,x2,...,xn。
這些人預先同意他們誰將交付給哪些客戶,然後他們的行為如下。當第i個客戶端的包裹被交付時,兩個快遞員中的其中乙個負責去送第i+1個。此時不送快遞員的那個原地不動。即快遞是嚴格按照顧客順序乙個個在送的,乙個快遞員在送的時候,另乙個快遞員是不動的。
由於要相互溝通,這些傢伙有對講機。對講機的工作距離不是很遠,所以petya和vasya想在送快遞的時候,使得他們的最大距離盡可能低。幫助petya和vasya儘量減少他們之間的最大距離,遵守所有交貨規則。
只有一行乙個正數,即最小可能的最大距離。第一行包含三個整數n,s1,s2(1≤n≤100000,0≤s1,s2≤10^9) - petya和vasya的送貨數量和起始位置。
第二行包含n個整數x1,x2,...,xn - 客戶座標(0≤xi≤10^9),以便交貨。
保證,在數字s1,s2,x1,...,xn中沒有兩個相等。
樣例輸入1
2 0 10
5 6樣例輸出1
樣例輸入2
3 2 1
3 4 5
樣例輸出2
樣例輸入3
1 4 5
2樣例輸出3
對於20%的資料,n<=25在第乙個測試案例中,快遞員之間的初始距離為10.這個值將是答案,例如,petya可以執行兩次交付,vasya將保持在起點。
在第二個測試用例中,您可以通過以下方式進行最佳的操作:vasya向第乙個客戶送貨,petya到第二個,最後,vasya將包提供給第三個客戶。按照這種交貨順序,快遞員之間的距離不會超過1。
在第三個測試用例中,只有兩種情況是可能的:如果單個包裝的交付由petya執行,則它們之間的最大距離為5 - 2 = 3.如果vasya將提供包裝,最大距離為4 - 2 = 2.後一種方法是最優的。
對於40%的資料, n<=100
對於60%的資料, n<=2000
對於100%的資料,n<=100000
1=s1
,x0=
s2如果用暴力做,就會生成下圖這樣一棵搜尋樹:
我們很容易發現,在第i層中,每個節點中必有i。
將i提取出來,再將重複的節點(反正每個節點中兩個數反過來都一樣)壓在一起,
可以得到下面這張圖:
從這張圖中,很容易得出結論:在第i層中,若i-1層有節點,必定會生成i-1的節點。
對於這一題,「最大距離盡可能低」,在乙個句子中,一旦最大、最小兩個詞一起出現,就要果斷二分(除非兩個是並列關係),這是我目前沒有見過例外的規律。
所以,先二分答案,然後判斷是否成立。
判斷是否成立時,我們考慮一層一層計算
如果第i-1層有節點k,那麼節點k就可以生成第i層的k節點和i-1節點
這意味著,若k在某一層(假設為j)被刪掉,那麼在以後j+1到n層就不會生成k。
還有之前已經得出的結論:在第i層中,若i-1層有節點,必定會生成i-1的節點。
在第i層,節點k必須滿足xk
∈[xi
−ans
,xi+
ans]
,不然就要被刪掉
所以我們可以枚舉行,在每一行刪掉不滿足這個條件的節點。若i-1行有節點,就試著加入i-1(若i-1不符合條件一樣要刪)。
若到第n層有節點,則這個答案是成立的。
為了更高效地刪除節點,我使用了平衡樹操作。
時間複雜度o(
lg109n
lgn)
#include
#include
#include
#include
using
namespace
std;
int n;
int _s[100010];
int* s=_s+1;
set q;
inline
bool ok(int);
int main()
printf("%d\n",res);
return0;}
inline
bool ok(int len)
return
1;}
//注釋同上
#include
#include
#include
using
namespace
std;
struct node
d[100001];
int cnt,root;
inline
void zig(int x)
d[x].r=y;
d[y].fa=x;
}inline
void zag(int x)
d[x].l=y;
d[y].fa=x;
}inline
void splay(int x,int t)
else
if (d[z].l==y)
else
if (d[z].r==y)
}if (!t)
root=x;
}inline
void insert(int x,int val)
; root=1;
return;
}while (1)
;d[x].l=cnt;
splay(cnt,0);
break;}}
else
if (val>d[x].val)
;d[x].r=cnt;
splay(cnt,0);
break;}}
}}inline
int pred(int val)
return ret;
} inline
int succ(int val)
else
x=d[x].r;
}return ret;
}int n;
int _s[100010];
int* s=_s+1;
inline
bool ok(int);
int main()
printf("%d\n",res);
return0;}
inline
bool ok(int len)
if (x=succ(up))
if (low<=s[i-1] && s[i-1]<=up)
insert(root,s[i-1]);
if (root==0)
return
0; }
return
1;}
set用紅黑樹實現,在這題中,splay的刪除相對高效。
刪掉小於low的節點時,只需把最大的小於low的節點旋轉到根,留下根的右子樹。
刪掉大於up的節點時道理一樣
set操作很簡單但跑得慢,splay要手打但跑得快。
有某位大佬發明了列舉列的演算法,完美利用資料的隨機性,能過!!!主要是有了一些break。但最壞情況下時間複雜度o(
lg109n
2)。在隨機資料下,時間遠遠沒有這麼多。 zhj的**,判斷是否成立時明顯兩重迴圈,卻跑了360ms。
2017 12 02普及組模擬 送快遞
petya和vasya被聘為快遞員。在工作日期間,他們將提供包裹到線上的不同點。根據公司的內部規定,包裹的交付必須嚴格按照一定的順序進行。最初,petya處於座標s1的點,vasya位於座標s2的點,n個顧客所需訪問的順序位於點x1,x2,xn。這些人預先同意他們誰將交付給哪些客戶,然後他們的行為如...
2017 12 02 NOIP提高組 模擬賽A組
t1 3555 gdkoi2014模擬 樹的直徑 t2 3542 清華集訓2014 氣泡排序 t3 3486 noip2013模擬聯考10 道路改建 rebuild 樹直徑的乙個性質,兩棵樹合併,形成新的樹的直徑的兩個端點為原樹中的四個端點之二。可以用反證法證明。用此性質本題就變成了lca裸題了 i...
普及組模擬賽 家族
題目描述 在乙個與世隔絕的島嶼上,有乙個有趣的現象 同乙個家族的人家總是相鄰的 這裡的相鄰是指東南西北四個方向 不同的家族之間總會有河流或是山丘隔絕,但同乙個家族的人不一定有相同姓氏。現在給你島上的地圖,求出島上有多少個不同的家族。島上的地圖有n 行,每行有若干列,每個格仔中要麼是 空格表示大海,要...