模板 莫隊演算法

2021-07-11 22:50:08 字數 1267 閱讀 8065

題意:給定乙個大小為n的陣列,陣列中所有元素的大小<=n。你需要回答m個查詢。每個查詢的形式是l,r,k。你需要回答在範圍[ l,r ]中至少重複k次的數字的個數。n,m<=100000

誒,這題卡了好久,tle,中間棄了一段,然後今天學弟學莫隊,拿出這個題,他也沒什麼想法,然後我頓時退一步海闊天空了。

最開始的想法是:莫隊排序,當前區間[l,r]->[l+1,r],修改乙個點,有兩個點的cnt變化(cnt[i]表示出現次數為i的數的個數),由於k不同,動態維護所有的k,然後求字首和。想到樹狀陣列。然而莫隊+樹狀陣列修改o(msqrt(n)logn) tle,問了學長,學長blabla說了個用平衡樹的,同樣超時。然後棄了。今天想了想,發現,區間求和還有另一種嘛,樹狀陣列修改log查詢log,塊狀陣列修改o(1),查詢o(sqrt(n))啊。瞬間解決了。。

交了之後看到**上還有別的神犇的做法更簡潔,考慮到求至少出現k次的,那麼出現x次的之前必有出現x-1次的狀態。就是相當於我們不做-1的操作直接+1,這樣最後答案直接是ans了。好神啊。

#include

#include

#include

#include

#define n 100005

struct qq[n];

int n,m,a[n],num[n],cnt[n],block[n],tot[n],end[n],begin[n];

using namespace std;

intread()

while(ch>='0'&&ch<='9')

return

x*f;

}bool cmp(q x,q y)

bool cmp2(q x,q y)

void upd(int

pos,int

x) num[a[pos]]+=x;

if(num[a[pos]]!=0)

}int getsum(int k)

int main()end[block[n]]=n;begin[block[n]+1]=n+1;end[block[n]+1]=n+1;

for(int i=1;i<=m;i++)

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

int l=0,r=0;

for(int i=1;i<=m;i++)

sort(q+1,q+1+m,cmp2);

for(int i=1;i<=m;i++) printf("%d\n",q[i].ans);

return

0;}

模板 莫隊演算法

這個演算法是由之前的國家隊隊長莫濤巨神 orz 發明的,所以尊稱莫隊演算法。如果我們知道區間 l,r 就能在o 1 求出 l 1,r l 1,r l,r 1 l,r 1 的話,那就可以用莫隊演算法了。1 排序,以左段點所在的塊為第一關鍵字,以右端點為第二關鍵字 2 從左往右處理詢問 離線 3 不斷調...

莫隊演算法模板

一道簡單的莫隊演算法題 莫隊的一般寫法 codeforces 86d include define pb push back define mp make pair using namespace std const int maxn 2e5 7 typedef long long ll struc...

莫隊演算法 普通莫隊 智慧型暴力例題模板

1 基礎莫隊演算法2.莫隊演算法實現 莫隊演算法把排序做了簡單的修改,就把暴力法的複雜度從o mn 提高到o n n 1 暴力法的排序 把查詢的區間按左端點排序,如果左端點相同,再按右端點排序。莫隊演算法的排序 把陣列分塊 分成 n塊 然後把查詢的區間按左端點所在塊的序號排序,如果左端點的塊相同,再...