動態中位數

2021-10-08 17:25:58 字數 3454 閱讀 7491

題意

注:本文的**中的輸出不嚴格正確,反正loj的資料也沒多強,不會pe。如果後面加強了當我沒說

沒錯,第乙個還是我的做法。

記得是哪年的scp還是noip初賽竟然程式題就是這個思路,然後我照搬了。

我們這道題目反著考慮,它讓我們加數,我們就刪除數字,從後往前刪除數字,我們先建乙個排好序的鍊錶,然後從中乙個個刪除數字,然後通過鍊錶來跳,由於每次最多刪除兩個數字,除2就是乙個,所以鍊錶每次最多跳一次,時間複雜度:o(n

logn

)o(nlogn)

o(nlog

n)。當然有一種情況要特殊考慮一下,就是當n=2

n=2n=

2時刪除到了中位數的位置,這種情況要處理一下,其他也就沒什麼了。

#include

#include

#include

#define n 11000

using

namespace std;

struct ****

a[n]

;inline

bool

cmp(**** x,**** y)

struct node

b[n]

;void

del(

int x)

int n,be[n]

;int list[n]

,top;

intmain()

sort

(a+1

,a+n+

1,cmp)

;for

(int i=

1;i<=n;i++

)be[a[i]

.y]=i,b[i]

.x=a[i]

.x;//確定其在鍊錶中的位置

int ans=n/2+

1,l=n/

2/*左邊有多少個數字*/

,r=n/

2/*右邊有多少個數字*/

;for

(int i=n;i>=

1;i--

)//按順序刪除

else

if(l>r)

list[

++top]

=b[ans]

.x;}

if(be[i]

==ans)

//剛好卡在中位數的位置

if(be[i]

>ans)r--

;else l--

;del

(be[i]);

}//後面就是輸出的問題了。

printf

("%d %d\n"

,t,n/2+

1);int now=0;

for(

int i=top;i>=

1;i--

)printf

("%d"

,list[i]);

if(now!=10)

printf

(" ");

}printf

("\n");

}return0;

}

搞兩個堆,然後不斷插入,如果siz

esize

size

之差≥ 2≥2

≥2了,時間複雜度:o(n

logn

)o(nlogn)

o(nlog

n)。(當然,兩個堆的做法也可以有其他實現方法(例如像做法1一樣,等到奇數再調節,而且最多調節一次),但本質上都是通過兩個堆求中間的數字。)

時間複雜度:o(n

logn

)o(nlogn)

o(nlog

n)

#include

#include

#include

#include

#include

#include

using

namespace std;

struct cmp1};

priority_queue <

int,vector<

int>

, cmp1> q1,kong1;

priority_queue <

int> q2,kong2;

void

init()

while

(q1.

size()

>q2.

size()

+1)}

if(i&1)

}puts(""

);}}

intmain()

838/

我們考慮用線段樹來找到中位數是哪個,對於第i

ii次而言,我們就是要找到i2+

1\frac+1

2i​+

1大的陣列,那麼能不能讓這個這麼大的數字自動找上門來呢?

我們先讓t[i

]=i2

+1

t[i]=\frac+1

t[i]=2

i​+1

我們排序一遍,然後從小到大看,如果這個數字x

xx原本就是在第i

ii次及之前插入的,我們就把t[i

]−

−t[i]--

t[i]−−

,如果t[i

]=

0t[i]=0

t[i]=0

了,那麼這個就是中位數。

不難發現,如果乙個數字是第i

ii次插入的話,那麼t[i

]t[i]

t[i]

~t [n

]t[n]

t[n]

都要減一。

那麼我們只要用線段樹管理t

tt陣列不就行了嗎?

但是怎麼處理t[i

]=

0t[i]=0

t[i]=0

的情況呢?

我們暴力儲存正數最小值,當正數最小值等於0

00時就暴力進入這個區域重複此操作,把為0

00的數拿出來同時更新最小值。

時間複雜度:對於管理[l,

r]

[l,r]

[l,r

]區間的節點,他最多有r−l

+1

r-l+1

r−l+

1次進入機會,所以全部節點的範圍加起來,就是o(n

logn

)o(nlogn)

o(nlog

n)啦。當然,這也能解決每一次插入求的不是中位數,而是第k

kk大的題目。

當然,由於這道題目只是當奇數的時候再查詢,所以可以處理一下減少常數,嫌麻煩也可以直接全部偶數設為inf,這樣也沒有多大問題。

沒有**。

平衡樹他不香嗎。(求i2+

1\frac+1

2i​+

1大值)

時間複雜度:o(n

logn

)o(nlogn)

o(nlog

n)

動態中位數

178.動態中位數 統計描述 提交自定義測試 題目描述 輸入n個32位有符號整數,當已輸入的個數為奇數個時,輸出此時的中位數。輸入描述 第一行乙個整數n 第二行n個32位有符號整數。輸出描述 輸出一行,n 2 上取整 個中位數,中間用空格隔開。對於 40 資料 n 1000 對於所有資料 n 100...

動態中位數

依次讀入乙個整數序列,每當已經讀入的整數個數為奇數時,輸出已讀入的整數構成的序列的中位數。輸入格式 第一行輸入乙個整數p,代表後面資料集的個數,接下來若干行輸入各個資料集。每個資料集的第一行首先輸入乙個代表資料集的編號的整數。然後輸入乙個整數m,代表資料集中包含資料的個數,m一定為奇數,資料之間用空...

動態中位數

include include include include define fir i,a,b for int i a i b i using namespace std priority queue,greater q1,kong1 priority queueq2,kong2 void ini...