BZOJ4241 歷史研究

2021-09-07 01:57:04 字數 1267 閱讀 9723

莫隊演算法,考慮如何快速維護最大的重要度。

考慮到答案一共只有$o(n)$種本質不同的取值,於是可以先通過$o(n\log n)$的排序處理出這些值的大小關係,並將這些值離散化,同時對每種事件的每個出現次數維護兩個指標pre和nxt,分別表示出現次數減少或增加一后是第幾小。

然後對這些取值進行分塊,每塊維護該塊內有哪些值出現過。

顯然,修改是$o(1)$的。

查詢的時候從後往前掃瞄,遇到第乙個有數字的塊就在該塊內從後往前掃瞄,時間複雜度$o(\sqrt)$。

於是總的複雜度為$o((n+q)\sqrt)$。

#include#include#includeusing namespace std;

typedef long long ll;

const int n=210000,k=9,buf=6000000,out=2000000;

struct queryask[n];

int n,q,m,lim,i,pos[n],a[n],b[n],c[n],ap[n];

int pre[n],nxt[n],loc[n],cnt,sum[n],en[n];ll ans[n];

struct pp(ll _x,int _y)}v[n];

inline bool cmpv(const p&a,const p&b)

inline void add(int x)

inline void del(int x)

inline ll askmax()

char buf[buf],*buf=buf,out[out],*ou=out;int outn[30],outcnt;

inline void read(int&a)

inline void write(ll x)

}int main()

cnt=m>>k;

for(i=1;i<=q;i++)read(ask[i].l),read(ask[i].r),ask[i].id=i;

sort(ask+1,ask+q+1,cmp);

for(i=1;i<=n;i++)ap[i]=1,sum[i>>k]++;

int*l=c+1,*r=c;

for(i=1;i<=q;i++)

ans[ask[i].id]=askmax();

} for(i=1;i<=q;i++)write(ans[i]),*ou++=10;

fwrite(out,1,ou-out,stdout);

return 0;

}

bzoj4241 歷史研究

這題也是坑了好久 之前whx帶我刷joi的時候本來應該要做的。可是太懶沒有寫。區間詢問加權眾數。分塊,預處理出塊和塊之間的答案,記錄到第i個塊數字x出現了多少次。然後查詢的時候和普通眾數基本一樣,就是乘了個權值而已。要離散化。時間複雜度o nlogn mn 昨晚寫的常數太爛了。用了struct,陣列...

BZOJ4241 歷史研究

一眼覺得是莫隊,發現刪除不是很好搞,於是上回滾莫隊直接搞過 回滾莫隊用於處理難以刪除但是易於新增 其實易於刪除難以新增也可以,但是沒見過這樣題 的莫隊,排序照常,如果左右端點在同一塊直接暴力,這部分最多n sqrt n,否則把左端點在一塊的一起處理,清空莫隊,然後直接令莫隊左端點在塊尾,這部分n s...

bzoj4241 歷史研究

題目鏈結 看到題目就聯想到了 bzoj2809 apio2012 dispatching。想了想權值分塊 莫隊,發現不好維護塊內最值,又看了看80s的時間,於是怒水一發線段樹 莫隊,結果先wa後tle,不斷tle,無論怎麼改常數都不行,難道nlogn sqrt n 就是過不了嗎!不爽,蒯個題解,再見...