1. 程式人生 > >BZOJ1878: [SDOI2009]HH的項鏈

BZOJ1878: [SDOI2009]HH的項鏈

上一個 gif bsp pan 樹狀 algorithm () print 排序

n<=50000個數字,m<=200000個查詢,每次問L到R之間有多少不同的數字。

這個詢問可以離線的,為使L到R之間的數字只被算一次,可以從左往右掃,掃到一個數字就把上一個該數字出現的地方--,把現在這裏++,為了配合這種操作,把所有詢問按右端點排序,掃到一個地方就把該處所有右端點在這裏的詢問回答了。--和++只需樹狀數組計算前綴和即可。

技術分享
 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<stdlib.h>
 4 //#include<assert.h>
 5 #include<math.h>
 6
#include<algorithm> 7 //#include<iostream> 8 using namespace std; 9 10 int n,m; 11 #define maxn 50011 12 struct BIT 13 { 14 int a[maxn]; 15 BIT() {memset(a,0,sizeof(a));} 16 void add(int x,int v) {for (;x<=n;x+=x&-x) a[x]+=v;} 17 int query(int x) {int ans=0;for (;x;x-=x&-x) ans+=a[x];return
ans;} 18 }t; 19 #define maxm 200011 20 struct Seg 21 { 22 int l,r,id; 23 bool operator < (const Seg &b) const {return r<b.r;} 24 }s[maxm]; 25 #define maxc 1000011 26 int pre[maxc],a[maxn],last[maxm]; 27 int main() 28 { 29 scanf("%d",&n); 30 for (int i=1;i<=n;i++) scanf("%d",&a[i]);
31 scanf("%d",&m); 32 for (int i=1;i<=m;i++) scanf("%d%d",&s[i].l,&s[i].r),s[i].id=i; 33 sort(s+1,s+1+m); 34 memset(pre,0,sizeof(pre)); 35 for (int i=1,j=1;i<=n;i++) 36 { 37 if (pre[a[i]]) t.add(pre[a[i]],-1); 38 t.add(i,1); pre[a[i]]=i; 39 while (j<=m && s[j].r<=i) 40 last[s[j].id]=t.query(s[j].r)-t.query(s[j].l-1),j++; 41 } 42 for (int i=1;i<=m;i++) printf("%d\n",last[i]); 43 return 0; 44 }
View Code

BZOJ1878: [SDOI2009]HH的項鏈