題目大意
解題思路
**題目描述
給定乙個長度為n的序列a,試求出對於序列a的每乙個字首的終極數x,使得
最小,試求出終極數t(如若有多個終極數t,只需輸出最小的那個)
第一行乙個整數n,第二行n個整數,中間用空格隔開
輸出一行乙個整數,即表示終極數t
由於題目較為苦澀難懂,【先看一下–>解題思路】,其實就是求出多個中位數後,再求多個中位數的中位數…
對於 20%的資料:直接暴力對於 40%的資料:顯然的,對於乙個序列的終極數,肯定就是這個序列的中位數,那麼可以用快排,做到 o( )
對於 100%的資料:找中位數,可以用堆,
我們維護兩個堆,乙個大根堆,乙個小根堆,當前每次加入乙個數,必須保證小根堆的個數大於等於大根堆的個數,亦即——第一次加入數的時候肯定是放到最小堆。
其次,我們還需保證小根堆裡的每個值必須大於等於大根堆當中的最大值。
並且,我們當前大根堆的個數如果已經小於小根堆的話,則要把下乙個數加到大根堆裡,反之亦然。
而當我們加入乙個數時,會有兩種特殊情況:
設加入的數為 x,如果欲加入到大根堆裡時,x 大於小根堆的堆頂,則進行 temp1 操作。
反之————— 如果欲加入到小根堆裡時,x 小於大根堆的堆頂,則進行 temp2 操作。
temp1:把 x 放到小根堆中,並且把小根堆的堆頂放到大根堆當中,並維護兩堆性質。
temp2:把 x 放到大根堆中,並且把大根堆的堆頂放到小根堆當中,並維護兩堆性質。
我們求的是每一次小根堆的堆頂…
#include
#include
using
namespace std;
int n,u,num,nuu,a[
1000001
],b[
1000001
],d[
1000001];
void
upa(
int x)
//因為有兩個根堆,方便操作,定義兩個up和down
void
downa
(int x)
//小跟堆
}void
upb(
int x)
void
downb
(int x)
//大根堆
}int
main()
else
}else
//否則放入大根堆裡
else
} d[i]
=a[1];
//取中位數
}sort
(d+1
,d+n+1)
;printf
("%d"
,d[n/2]
);//取多個中位數中的中位數
return0;
}
DP 2017 7 7普及 和諧數
題目描述 給定乙個長度為n nn的序列a aa,對於每乙個數都可選或不選,把選出的數有序組成乙個新的序列b bb,使b bb序列的 和諧數 最大。乙個序列的和諧數如下定義 對於位置i ii,如果第奇數次選的則加上b ib i bi 偶數次選的則減去b ib i bi 注意 新的序列b bb必須是從左...
數學 2017 7 7普及 串
題目描述 給定乙個0 1串,請找到乙個盡可能長的子串,其中包含的0與1的個數相等。輸入 乙個字串,只包含01,長度不超過1000000。輸出 一行乙個整數,最長的0與1的個數相等的子串的長度。樣例輸入 1011 樣例輸出 2資料範圍限制 30 的資料 串的長度 20 思路題面看著這麼舒服,結果難的跟...
jzoj P2152 2017 7 7普及 終極數
題目大意 給定乙個長度為n的序列a,試求出對於序列a的每乙個字首的終極數x,使得 最小,試求出終極數t 如若有多個終極數t,只需輸出最小的那個 題解 雖然看似很迷,其實就是每次插入後的中位數中排序後的中位數 我們維護兩個堆來處理,乙個大根堆,乙個小根堆,當前每次加入乙個數,必須保證 小根堆的個數大於...