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

洛谷1972 [SDOI2009]HH的項鏈

urn 就是 color 一個點 。。 strong 含義 lowbit 下一個

題目描述

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

輸入格式:

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

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

第三行:一個整數M,表示HH 詢問的個數。

接下來M 行:每行兩個整數,L 和R(1 ≤ L ≤ R ≤ N),表示詢問的區間。

輸出格式:

M 行,每行一個整數,依次表示詢問對應的答案。

可以樹狀數組求前綴和來離線做,在線做似乎需要主席樹,菜雞的我並不會主席樹。。

首先用p數組記錄一下每種顏色最左端的位置,用next數組來記錄每種顏色下一個的位置

把詢問按照左端點排序,碰到一個點x就將a[next[x]]++

每次詢問就是sum[r]-sum[l-1]

sum數組是a的前綴和

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace
std; #define maxn 50005 #define maxm 200005 int a[maxn],c[maxn]; struct data{ int l,r,ans,id; }q[maxm]; int next[maxn],p[maxn*20]; int n,m; int lowbit(int x){return x&(-x);} bool cmp1(data a,data b){ return a.l==b.r?a.r<b.r : a.l<b.l; } bool cmp2(data a,data b){ return a.id<b.id; }
void update(int x,int v){ for(int i=x;i<=n;i+=lowbit(i)){ c[i]+=v; } } int ask(int x){ int res=0; for(int i=x;i;i-=lowbit(i))res+=c[i]; return res; } int mx; int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); mx=max(mx,a[i]); } for(int i=n;i>0;i--){ next[i]=p[a[i]]; p[a[i]]=i; } for(int i=0;i<=mx;i++){ if(p[i])update(p[i],1); } scanf("%d",&m); for(int i=1;i<=m;i++){ scanf("%d%d",&q[i].l,&q[i].r); q[i].id=i; } sort(q+1,q+1+m,cmp1); int l=1; for(int i=1;i<=m;i++){ while(l<q[i].l){ if(next[l])update(next[l],1); l++; } q[i].ans=ask(q[i].r)-ask(q[i].l-1); } sort(q+1,q+1+m,cmp2); for(int i=1;i<=m;i++){ printf("%d\n",q[i].ans); } }

洛谷1972 [SDOI2009]HH的項鏈