标签:
对于20%的数据,N ≤ 100,M ≤ 1000;
对于40%的数据,N ≤ 3000,M ≤ 200000;
对于100%的数据,N ≤ 50000,M ≤ 200000。
【思路】
离线处理+BIT
将颜色相同的节点串成链。离线处理所有询问,对于n个位置建一棵BIT,对于多个颜色,我们将该颜色在区间左端点右边的第一次出现的位置设为1,当该颜色移出区间左端点的时候我们把该颜色的下一个出现位置设为1,这样就可以用BIT查询区间中不同的颜色个数了。
【代码】
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 6 const int N = 1e6+5; 7 struct Node { 8 int l,r,id; 9 bool operator < (const Node& rhs) const { 10 return l<rhs.l||(l==rhs.l&&r<rhs.r); 11 } 12 }que[N]; 13 14 int n,m,C[N],mx,a[N],ans[N]; 15 int front[N],next[N]; 16 17 void add(int x,int v) { 18 for(;x<=n;x+=x&-x) C[x]+=v; 19 } 20 int sum(int x) { 21 int res=0; 22 for(;x>0;x-=x&-x) res+=C[x]; 23 return res; 24 } 25 26 int main() { 27 scanf("%d",&n); 28 for(int i=1;i<=n;i++) { 29 scanf("%d",&a[i]); 30 mx=max(mx,a[i]); 31 } 32 for(int i=n;i>0;i--) //倒序加入 正序成链 33 next[i]=front[a[i]],front[a[i]]=i; 34 for(int i=1;i<=mx;i++) 35 if(front[i]) add(front[i],1); 36 scanf("%d",&m); 37 for(int i=1;i<=m;i++) { 38 scanf("%d%d",&que[i].l,&que[i].r); 39 que[i].id=i; 40 } 41 sort(que+1,que+m+1); 42 int l=1; 43 for(int i=1;i<=m;i++) { 44 while(l<que[i].l) { 45 if(next[l]) add(next[l],1); 46 l++; 47 } 48 ans[que[i].id]=sum(que[i].r)-sum(que[i].l-1); 49 } 50 for(int i=1;i<=m;i++) 51 printf("%d\n",ans[i]); 52 return 0; 53 }
bzoj 1878 [SDOI2009]HH的项链(离线处理+BIT)
标签:
原文地址:http://www.cnblogs.com/lidaxin/p/5225467.html