這題就是求區間權值乘以權值出現次數的最大值,一看莫隊法塊可搞,但仔細想想,莫隊的加入很容易,但是刪除需要維護許多東西,非常麻煩,於是就有dalao想出了乙個新科技--回滾莫隊.回滾莫隊能使操作全部變成加入或全部變成刪除.這道題我們需要全部變成加入.
怎麼做呢?我們對詢問進行處理,左端點在乙個塊中的先歸在一起,然後以右端點為關鍵字進行排序,使得右端點靠前的在前.然後依次處理按左端點歸好後每個塊中的詢問,我們找到塊中最靠後的左端點,和最靠前的右端點(其實就是塊中第乙個詢問的右端點),統計區間資訊。
對於每乙個詢問,先移動右端點加入元素,然後左端點左移得到詢問答案後再向右移撤銷,由於不需要維護什麼資訊撤銷變得非常容易.簡單來說,總的思路就是先找出最「窄」的區間,然後不斷加入補全到詢問區間.
當然,如果詢問的左端點和右端點在乙個塊中就直接暴力處理
#include #include #include #include #include #include #include #include #include #define ll long long
#define ri register int
using std::min;
using std::max;
using std::vector;
using std::map;
template inline void read(t &x)
struct qur
bool operator <(const qur & b)const
int main()w[i]=g[w[i]];
pos[i]=(i-1)/blo+1;
}for(ri i=1;i<=q;i++)
else
}int ll,rr;ll last;
for(ri i=1;i<=pos[n];i++){//處理每個詢問塊
if(qry[i].empty())continue;
memset(cnt,0,sizeof(cnt));res=-inf;
sort(qry[i].begin(),qry[i].end());
l=mxl[i],r=qry[i][0].r;
for(ri j=l;j<=r;j++)add(w[j]);
for(ri j=0;j關於這題的離散化處理,我還進行了一些比較,在這篇部落格中
學習筆記-幾種離散化方式/
推薦學習部落格
BZOJ4241歷史研究題解
題目連線 很顯然可以想到分塊,用f i j 表示塊i到塊j的ans,然後發現答案一定是f i j 或者其他在邊角出現的數字 我們在記下g i j 從開頭到塊i中的數字j出現的次數 這樣就每一次就統計邊角數字出現的次數,然後更新答案就好了 好像莫對也可以做。注意每一次查詢時不要memset,會t飛 i...
bzoj4241 歷史研究
這題也是坑了好久 之前whx帶我刷joi的時候本來應該要做的。可是太懶沒有寫。區間詢問加權眾數。分塊,預處理出塊和塊之間的答案,記錄到第i個塊數字x出現了多少次。然後查詢的時候和普通眾數基本一樣,就是乘了個權值而已。要離散化。時間複雜度o nlogn mn 昨晚寫的常數太爛了。用了struct,陣列...
BZOJ4241 歷史研究
一眼覺得是莫隊,發現刪除不是很好搞,於是上回滾莫隊直接搞過 回滾莫隊用於處理難以刪除但是易於新增 其實易於刪除難以新增也可以,但是沒見過這樣題 的莫隊,排序照常,如果左右端點在同一塊直接暴力,這部分最多n sqrt n,否則把左端點在一塊的一起處理,清空莫隊,然後直接令莫隊左端點在塊尾,這部分n s...