[洛谷1972][SDOI2009]HH的項鏈
阿新 • • 發佈:2017-11-13
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的項鏈