即使是分塊也無法簡單的合併兩個塊的資料,所以我們考慮分塊的本質—— 暴力,直接維護塊合併後的資訊
用\(f[i][j]\)表示第i塊到第j塊這一段的眾數,那麼接下來就可以只考慮怎麼加入兩頭的數
考慮暴力求眾數的做法:記錄當前的眾數以及所有數的出現次數,如果新加入的數的出現次數大於眾數,那麼它取代原眾數成為新的眾數
改進暴力做法。同樣,我們每次詢問開了乙個桶存眾數的出現次數,但問題是我們不能暴力加每乙個數,所以我們還要知道第i個塊到第j個塊這一段中每乙個數的出現次數,於是我們要開乙個三維陣列[i][j][k],這樣顯然會爆記憶體,改進方法顯然就是字首和,用sum[i][k]表示存了前i塊資料的桶即可
查詢乙個區間,我們要先讀取i到j塊的桶,但暴力每個數都讀取仍舊會\(o(n)\)超時,所以我們考慮哪一些不可能成為眾數,就不讀取它的桶,思考發現除了f[i][j]之外可能成為眾數的只有邊角上出現了的數,只讀取它們的桶就可以做到\(\sqrt\)
總結思路:預處理出f,sum兩個陣列,大塊直接調取f[i][j],邊角先從sum中讀取桶再按照暴力方法直接加數
code:
#include#define n 40005
#define s 205
using namespace std;
int n,m,x=0,a[n];
int size,cnt,sum[s][n],f[s][s];
int l[s],r[s],pos[n],tng[n];
int b[n],len;
template inline void read(t &x)
inline int get_lit(int x)
void init()
for(int i=1;i<=n;++i)
for(int i=1;i<=cnt;++i)
return 0;
}
這道題與其說是分塊不如說是一道模擬題,按照暴力思路直接優化就不難得到正解 Violet 蒲公英 分塊
題解 講道理,關於區間眾數問題應該第乙個就想到分塊,可毒瘤出題人說是線段樹.qaq 考慮查詢的區間 l,r 第一種情況,我們可以考字首和以及遞推來進行預處理,查詢的時候直接呼叫即可。第二種情況,我們開乙個桶,將 2 個端點所在不完整塊進行統計,再用乙個 vector 加上中間完整整塊對這些顏色的貢獻...
P4168 Violet 蒲公英 分塊
題目鏈結 分塊。p i j 表示第 i 個塊到第 j 個塊內的眾數,預處理出來就好了,列舉 i 和 j 是 o sqrt n 的,列舉 j 塊內的數也是 o sqrt n 的,總複雜度 o n sqrt n sum i h 表示前 i 個塊數字 h 出現的個數,預處理是 o n 的。對於每乙個查詢,...
BZOJ2724 Violet 6 蒲公英 分塊
n 個數,m 次詢問。n leq 40000,m leq 50000 看完題目 呀這不是莫隊裸題嗎?然後經過一波思 forever 考 piano 終於會做了。首先請你自行證明乙個結論 在詢問區間內任取一段子區間,詢問區間內的最小眾數一定是子區間的最小眾數或者出現在詢問區間除掉子區間的其他地方。於是...