1. 程式人生 > >[洛谷1972][SDOI2009]HH的項鏈

[洛谷1972][SDOI2009]HH的項鏈

name i++ badge print cnblogs nbsp 貝殼 指針 sqrt

題目描述

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。

莫隊

用cnt[i]表示數i的出現次數,sum表示當前區間的數的種類,移動指針時,若cnt[i]==1,sum++,cnt[i]==0,sum--

cnt表示的是數的出現次數,不是數的下標的出現次數,容易誤打

#include<iostream>
#include<cstdio>
#include<algorithm>
#include
<cmath> using namespace std; struct xxx{ int l,r,block,id; }q[200001]; int a[50001],cnt[1000100],ans[200001]; bool cmp(xxx a,xxx b){if(a.block!=b.block)return a.block<b.block;return a.r<b.r;} int main() { int n,m;scanf("%d",&n);int T=(int)sqrt((double)n); for(int i=1;i<=n;i++)scanf("
%d",&a[i]); scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%d%d",&q[i].l,&q[i].r);q[i].block=(q[i].l+1)/T;q[i].id=i; } sort(q+1,q+m+1,cmp); int l=1,r=0,sum=0; for(int i=1;i<=m;i++) { while(r<q[i].r){cnt[a[++r]]++;if(cnt[a[r]]==1)sum++;} while(r>q[i].r){cnt[a[r]]--;if(cnt[a[r--]]==0)sum--;} while(l<q[i].l){cnt[a[l]]--;if(cnt[a[l++]]==0)sum--;} while(l>q[i].l){cnt[a[--l]]++;if(cnt[a[l]]==1)sum++;} ans[q[i].id]=sum; } for(int i=1;i<=m;i++)printf("%d\n",ans[i]); return 0; }

[洛谷1972][SDOI2009]HH的項鏈