給出乙個長度為\(n\)的序列\(a\),首先求出其所有區間的中位數,將這些中位數構成的集合記為\(s\),求\(s\)中所有數的中位數。
此題中位數指:有\(n\)個數,第\(\left \lfloor \frac \right \rfloor+1\)個數即為中位數。
資料範圍:\(1\leq n\leq 10^5,1\leq a_i\leq 10^9\)。
因為求的是\(s\)的中位數,發現答案具有單調性,考慮二分。
二分答案記為\(x\),判斷它是否是\(s\)的中位數。那就要看區間中位數\(\leq x\)的有多少個,從而確定這個數在集合\(s\)中的位置,記為\(res\)。
發現如果列舉的時間複雜度高,可以轉換一下方式,考慮判斷單個區間\([l,r]\)的中位數與\(x\)的大小關係,再看有多少個滿足條件的區間。
設\(p_i\)為\([1,i]\)中\(>x\)數的個數。如果區間\([l,r]\)的中位數\(\leq x\),可以得到\(r-l+1>2*(p_r-p_)\)(即\(>x\)的個數沒有達到區間個數的一半)。
然後看這個判斷的式子,可以變成\(r-(l-1)>2*(p_r-p_)\),移項變成\(r-2*p_r>(l-1)-2*p_\)。
發現對於乙個區間右端點\(r\),滿足這個式子的\(l-1\)的個數即為\(res\)。可用樹狀陣列維護這個答案。
然後就是根據\(res\)進行答案區間的縮小。記實際中位數的位置為\(w\),因為求的\(res\)是\(\leq x\)的個數(即是一段相同的\(x\)的最後乙個,如122333中2的res是3,3的res是6),所以滿足\(x\)的範圍包括了\(w\),即要使\(res\)是\(w\)的後繼(第乙個\(\geq w\)的數),所以二分求的是這麼乙個東西。
一些細節:\(s\)的區間長度會超出\(int\)。
對於\(i-2*p_i\)這個東西的範圍,是\(-n\sim n\)的,所以下標都加上\(n\)
二分的細節,比較多,建議重新看回藍書。詳見**。
#include #include #include #define int long long
int n, m;
int a[100001], b[100001], p[100001], t[200001];
void add(int x)
int query(int x)
int check(int x)
return tot < m / 2 + 1;
}signed main()
printf("%lld", b[l]);
}
luogu P1168 中位數 樹狀陣列 二分
題目描述 給出乙個長度為nn的非負整數序列a i,對於所有1 k n 1 21 k n 1 2,輸出a 1,a 3,a 2k 1的中位數。即前1,3,5,個數的中位數。輸入格式 第1行為乙個正整數n,表示了序列長度。第2行包含n個非負整數a i a i 10 9 輸出格式 共 n 1 2 n 1 2...
中位數(DP 二分)
單點時限 10.0 sec 記憶體限制 256 mb 你的地圖是一張白紙,所以即使想決定目的地,也不知道路在 qq 小方最近在自學圖論。他突然想出了乙個有趣的問題 一張由 n 個點,m 條邊構成的有向無環圖。每個點有點權 ai。qq 小方想知道所有起點為 1 終點為 n 的路徑中最大的中位數是多少。...
每日演算法 二分,中位數
題目 4.尋找兩個正序陣列的中位數 給定兩個大小為 m 和 n 的正序 從小到大 陣列 nums1 和 nums2。請你找出這兩個正序陣列的中位數,並且要求演算法的時間複雜度為 o log m n 你可以假設 nums1 和 nums2 不會同時為空。示例 1 nums1 1,3 nums2 2 則...