BZOJ1878 [SDOI2009] HH的项链(树状数组)
树状数组求区间不同种类的数模板
树状数组来存储前缀和,对于每个数我们记录他上一次出现的位置,
把查询按照右端点从小到大排序
对于每个数我们对add(pre[i],-1) add(i,1);
每个数字只有他当前最后一个位置贡献次数(查询区间已排序)
最后sum[r]-sum[l-1]就是答案
/************************************************************** Problem: 1878 User: Minun Language: C++ Result: Accepted Time:1728 ms Memory:10276 kb ****************************************************************/ #include<bits/stdc++.h> using namespace std; const int maxn=1e6+10; const double EPS=1e-12; #define mem(a,b) memset(a,b,sizeof(a)) #define ll long long int tree[50005]; int ans[600005],pre[50005]; int vis[maxn]; int n; struct node{ int l,r,id; }e[200005]; inline int lowbit(int x) { return x&(-x); } inline void add(int x,int val) { while(x<=n) { tree[x]+=val; x+=lowbit(x); } } inline int sum(int x) { int temp=0; while(x>0) { temp+=tree[x]; // x=x&(x-1); x-=lowbit(x); } return temp; } int cmp(node a,node b) { return a.r==b.r?a.l<b.l:a.r<b.r; } int main() { scanf("%d",&n); int now; for(int i=1;i<=n;i++) { scanf("%d",&now); pre[i]=vis[now]; vis[now]=i; } int m; scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%d%d",&e[i].l,&e[i].r); e[i].id=i; } sort(e+1,e+1+m,cmp); int st=1; st=0; for(int i=1;i<=m;i++) { while(st<e[i].r) { st++; if(pre[st]) { add(pre[st],-1); } add(st,1); } ans[e[i].id]=sum(e[i].r)-sum(e[i].l-1); } for(int i=1;i<=m;i++) { printf("%d\n",ans[i]); } return 0; }