莫隊演算法,考慮如何快速維護最大的重要度。
考慮到答案一共只有$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 就是過不了嗎!不爽,蒯個題解,再見...