區間查詢神器
莫隊演算法:
考慮優化,如何盡可能的利用已經求過的值,這是莫隊演算法的核心
但如何使l和r移動的次數盡可能少而覆蓋所有的詢問,是莫隊所要解決的
比如n=9,有以下的詢問:
2 3
1 4
4 5
1 6
7 9
8 9
5 8
6 8
對於n=9,我們以根號n為每個塊block的大小,這裡block=3.
那麼我們把1~3分成一組,4~6,7~9.
對於每乙個詢問(l,r),我們以l的範圍來決定這個詢問在哪乙個塊。
然後每乙個獨自的塊內,我們讓詢問r更小的排在更前面。
那麼上面的詢問就可以分組成:
(2,3)/(1,4)/(1,6)和
(4,5)/(5,8)/(6,8)和
(7,9)/(8,9)
分塊的意義就在於此
題目背景
無 題目描述
hh 有一串由各種漂亮的貝殼組成的項鍊。hh 相信不同的貝殼會帶來好運,所以每次散步完後,他都會隨意取出一段貝殼,思考它們所表達的含義。hh 不斷地收集新的貝殼,因此,他的項鍊變得越來越長。有一天,他突然提出了乙個問題:某一段貝殼中,包含了多少種不同的貝殼?這個問題很難回答……因為項鍊實在是太長了。於是,他只好求助睿智的你,來解決這個問題。
輸入輸出格式
輸入格式:
第一行:乙個整數n,表示項鍊的長度。
第二行:n 個整數,表示依次表示項鍊中貝殼的編號(編號為0 到100000 之間的整數)。
第三行:乙個整數m,表示hh 詢問的個數。
接下來m 行:每行兩個整數,l 和r(1 ≤ l ≤ r ≤ n),表示詢問的區間。
輸出格式:
m 行,每行乙個整數,依次表示詢問對應的答案。
輸入輸出樣例
輸入樣例#1:
6 1 2 3 4 3 5
3 1 2
3 5
2 6
輸出樣例#1:
2 2
4
#include
using
namespace
std;
#define maxn (1000000+10)
struct node
ask[maxn];
int l,r,now,n,m;
int cnt[maxn],a[maxn];
bool cmp1(node a,node b)
void ins(int x)
void mo(int x)
int main()
sort(ask+1,ask+m+1,cmp1);//區間排序
for (int i=1;i<=m;++i) mo(i);
sort(ask+1,ask+m+1,cmp2);//變回原來的樣子
for (int i=1;i<=m;++i)
printf("%d\n",ask[i].ans);
return
0;}
後來這題資料達到了100w 莫隊涼了 樹上莫隊演算法
繼續回來寫部落格 記錄點有意思的題目什麼的。貌似寫過這個的沒多少人 所以我也記錄一點。首先序列上的莫隊大家都應該很熟悉了 那麼樹上的莫隊要怎麼搞呢?先來看個題目 spoj cot2 求樹上兩點間路徑上有多少個不同的點權。序列上的莫隊是把詢問按照左端點分塊了 可是樹上沒有左端點,怎麼辦呢?我們把樹分塊...
模板 莫隊演算法
題意 給定乙個大小為n的陣列,陣列中所有元素的大小 n。你需要回答m個查詢。每個查詢的形式是l,r,k。你需要回答在範圍 l,r 中至少重複k次的數字的個數。n,m 100000 誒,這題卡了好久,tle,中間棄了一段,然後今天學弟學莫隊,拿出這個題,他也沒什麼想法,然後我頓時退一步海闊天空了。最開...
模板 莫隊演算法
這個演算法是由之前的國家隊隊長莫濤巨神 orz 發明的,所以尊稱莫隊演算法。如果我們知道區間 l,r 就能在o 1 求出 l 1,r l 1,r l,r 1 l,r 1 的話,那就可以用莫隊演算法了。1 排序,以左段點所在的塊為第一關鍵字,以右端點為第二關鍵字 2 從左往右處理詢問 離線 3 不斷調...