【树状数组】bzoj2743 [HEOI2012]采花

http://www.cnblogs.com/proverbs/archive/2012/10/29/2745281.html

(↑)这样处理之后,每次询问时,对于每种颜色,从1到其倒数第二次出现的位置都会被覆盖1次,因此询问左端点的值即可。

#include<cstdio>
#include<algorithm>
using namespace std;
#define N 1000001
int n,K,m,a[N],pre[N],anss[N],now[N];
struct ASK{int l,r,id;}Q[N];
bool operator < (ASK a,ASK b){return a.r<b.r;}
int d[N];
void Update(int p,int v){for(;p<=n;p+=(p&(-p))) d[p]+=v;}
void UpdateRange(int L,int R){Update(L,1); if(R<n) Update(R+1,-1);}
int Query(int p){int res=0; for(;p;p-=(p&(-p))) res+=d[p]; return res;}
int main()
{
	scanf("%d%d%d",&n,&K,&m);
	for(int i=1;i<=n;++i)
	  {
	  	scanf("%d",&a[i]);
	  	pre[i]=now[a[i]];
	  	now[a[i]]=i;
	  }
	for(int i=1;i<=m;++i)
	  {
	  	scanf("%d%d",&Q[i].l,&Q[i].r);
	  	Q[i].id=i;
	  }
	sort(Q+1,Q+m+1);
	for(int i=1;i<=m;++i)
	  {
	  	for(int j=Q[i-1].r+1;j<=Q[i].r;++j)
	  	  if(pre[j])
	  	    UpdateRange(pre[pre[j]]+1,pre[j]);
	  	anss[Q[i].id]=Query(Q[i].l);
	  }
	for(int i=1;i<=m;++i) printf("%d
",anss[i]);
	return 0;
}
原文地址:https://www.cnblogs.com/autsky-jadek/p/4442121.html