洛谷某討論
對於一串長度為n(n
<
=2000
)n(n<=2000)
n(n<=2
000)
的序列,對於所有的i,j
(1
<=i
<=n
,i
<=j
<=n
)i,j(1<=i<=n,i<=j<=n)
i,j(
1<=i
<=n
,i<=j
<=n
)區間,求出他們的中位數。
這個ider先在這裡佔坑吧,畢竟感覺這個思路挺好的。
我們可以一開始把整個序列排序,然後對排序後的陣列鍊錶化,並且求出每個點在鍊錶中的下標。
那麼對於固定的l
ll,我們的r
rr從大到小查詢,我們對於[l,
n]
[l,n]
[l,n
]暴力在鍊錶找中位數,然後對於[l,
n−1]
[l,n-1]
[l,n−1
]我們可以把n
nn在鍊錶中刪掉,然後看看中位數向左還是向右,這個是o(1
)o(1)
o(1)
的。然後我們可以o(1
)o(1)
o(1)
將[ l,
n]
[l,n]
[l,n
]的排序鍊錶推到[l+
1,n]
[l+1,n]
[l+1,n
]的排序鍊錶,不過我們需要拷貝陣列,為o(n
)o(n)
o(n)
,當然我朋友的**是遞迴實現,所以不用拷貝。
**來自hyy大神的,當然也是他最先提出這個問題。
注意:至於偶數的中位數,貌似這位神犇的**是取左邊的那個數字
#include
#include
using
namespace std;
const
int n=
2005
;int a[n]
,p[n]
,l[n]
,r[n]
,w[n]
;bool
cmp(
int x,
int y)
int f[n]
[n];
void
dfs(
int i,
int k,
bool bk,
int now)
else
int r1=r[l[j]
],l1=l[r[j]];
//tmp
r[l[j]
]=r[j]
;l[r[j]
]=l[j]
; f[i]
[k-1
]=a[p[now]];
dfs(i,k-
1,bk^
1,now/*目前中位數的位置*/);
r[l[j]
]=r1;l[r[j]
]=l1;}}
void
make
(int n)
else
r[l[j]
]=r[j]
;l[r[j]
]=l[j]
;bk^=1
/*奇偶性質*/
;//刪數
f[i+1]
[n]=a[p[now]];
dfs(i+
1,n,bk,now)
;//處理中位數}}
intmain()
return0;
}
區間中位數兩例
給定陣列 a 1,a 2,dots,a n hihocoder 1849 子陣列的中位數 中位數數定義為排序後第 floor 個數。中位數大於 k 等價於陣列中大於等於 k 的數超過一半。定義陣列 b 1,b 2,dots,b n begin b i begin 1,text,1,text.end ...
維護動態區間的中位數
依次讀入乙個整數序列,每當已經讀入的整數個數為奇數時,輸出已讀入的整數構成的序列的中位數。詳細內容 最樸素寫法,每到奇數時位將前面所有資料排序,找到中位數 每次sort是 o nlog n 一組資料需要sort frac 次,所以複雜度為 o n 2log n include include usi...
中位數的中位數
參照王曉東的演算法設計 中位數的中位數,即將一串數分成n段,求其排好序了的中間那個數,再把這些所有中位數再求一次中位數。for int i 0 i r p 4 5 i 找中位數的中位數,r p 4即上面所說的n 5 int x lineselect a,p,p r p 4 5,r p 4 10 線性...