1. 程式人生 > >算法之 莫隊 區間處理神器orz

算法之 莫隊 區間處理神器orz

stream cor 描述 sqrt scan work 一個 模板 算法

例題:luogu P1972 [SDOI2009]HH的項鏈

題目背景

題目描述

HH 有一串由各種漂亮的貝殼組成的項鏈。HH 相信不同的貝殼會帶來好運,所以每次散步完後,他都會隨意取出一段貝殼,思考它們所表達的含義。HH 不斷地收集新的貝殼,因此,他的項鏈變得越來越長。有一天,他突然提出了一個問題:某一段貝殼中,包含了多少種不同的貝殼?這個問題很難回答……因為項鏈實在是太長了。於是,他只好求助睿智的你,來解決這個問題。

輸入輸出格式

輸入格式:

第一行:一個整數N,表示項鏈的長度。

第二行:N 個整數,表示依次表示項鏈中貝殼的編號(編號為0 到1000000 之間的整數)。

第三行:一個整數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

說明

數據範圍:

對於100%的數據,N <= 50000,M <= 200000。

題解

莫隊真是好玩orz,存一下模板ovo

 1 #include <iostream>
 2 #include <cstdio>
 3
#include <algorithm> 4 #include <cmath> 5 #define maxn 50010 6 #define maxm 200005 7 using namespace std; 8 int a[maxn],cor[maxn],ans[maxn]; 9 struct Q{ 10 int l,r,id,belong; 11 }q[maxm]; 12 int n,m,block,cnt; 13 int comp(Q a,Q b) { 14 if(a.belong == b.belong) return a.r<b.r;
15 return a.belong<b.belong; 16 } 17 void del(int x) { 18 cor[a[x]]--; 19 if(cor[a[x]] == 0) cnt--; 20 } 21 void add(int x) { 22 cor[a[x]]++; 23 if(cor[a[x]] == 1) cnt++; 24 } 25 void work() { 26 int l=1,r=0; 27 for(int i=1;i<=m;i++) { 28 while(l<q[i].l) del(l),l++; 29 while(l>q[i].l) l--,add(l); 30 while(r<q[i].r) r++,add(r); 31 while(r>q[i].r) del(r),r--; 32 ans[q[i].id]=cnt; 33 } 34 } 35 int main() { 36 scanf("%d",&n); 37 block=sqrt(n); 38 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 39 scanf("%d",&m); 40 for(int i=1;i<=m;i++) { 41 scanf("%d%d",&q[i].l,&q[i].r); 42 q[i].id=i; 43 q[i].belong=(q[i].l-1)/block+1; 44 } 45 sort(q+1,q+1+m,comp); 46 work(); 47 for(int i=1;i<=m;i++) printf("%d\n",ans[i]); 48 return 0; 49 }

算法之 莫隊 區間處理神器orz