ACM 莫隊演算法

2021-08-21 03:28:18 字數 1630 閱讀 5521

區間查詢神器

莫隊演算法:

考慮優化,如何盡可能的利用已經求過的值,這是莫隊演算法的核心

但如何使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 不斷調...