題意:給定乙個大小為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塊 然後把查詢的區間按左端點所在塊的序號排序,如果左端點的塊相同,再...