区间种类统计类问题

1. 莫队算法

将询问按照左端点分为sqrt级别块进行排序,然后顺序处理.

例题 小Z的袜子

2. 树状数组

一种很有技巧性的东西

对于一些离线的这类问题,我们可能要统计在一段区间内的种类数,那么我们可以用差分的办法维护前缀和.

具体地说,我们将询问按左端点排序,那么我们就可以从左到右处理了.

看代码比较清楚,好好想一想就懂了.

SDOI HH的项链

#include <cstdio>
#include <algorithm>
int a[60000],p[60000],bit[60000],n,m,i,j,k,c[2000000];
#define lowbit(x) (x&(-x))
inline int read(){
    int x=0;char ch=getchar();
    while(ch<'0'||ch>'9'){ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x;
}
inline void add(int a){
	for(;a<=n;a+=lowbit(a)) ++bit[a];
}
inline int qry(int a){
	int res=0;
	for(;a;a-=lowbit(a)){
		res+=bit[a];
	}
	return res;
}
inline void cons(){
	for(i=1;i<=n;++i){
		bit[i]+=a[i];
		bit[i+lowbit(i)]+=bit[i];
	}
}
struct query{
	int l,r,id;
} qrs[300000];
bool cmp(const query& a,const query& b){
	return a.l<b.l;
}
int qrp;
int ans[300000];
char s[8000000],pp[15];
int strl,strp;
void record(int i){
    strp=0;
    while(i){
        j=i/10;
        pp[strp++]=i-j*10+'0';
        i=j;
    }
    while(~(--strp)){
        s[strl++]=pp[strp];
    }
    s[strl++]='\n';
}
int main(){
	n=read();
	for(i=1;i<=n;++i){
		j=read();
		if(!c[j]) a[i]=1;
		c[j]=p[c[j]]=i;
	}
	m=read();
	for(i=0;i<m;++i) qrs[i].l=read(),qrs[i].r=read(),qrs[i].id=i;
	std::sort(qrs,qrs+m,cmp);
	cons();
	qrp=0;
	for(i=1;i<=n;++i){
		if(qrs[qrp].l==i){
			j=qry(i-1);
			while(qrs[qrp].l==i&&qrp<m){
				ans[qrs[qrp].id]=qry(qrs[qrp].r)-j;
				++qrp;
			}
		}
		if(p[i]) add(p[i]);
	}
	for(i=0;i<m;++i) record(ans[i]);
	s[strl-1]='\0';
	puts(s);
	return 0;
}

read()函数是读入,record用来输出,add就是树状数组的update,qry就是树状数组的查询,cons从a中构造树状数组.

#include <cstdio>
#include <algorithm>
int a[1000010],p[1000010],bit[1000010],n,m,i,j,k,c[1000010],q[1000010];
#define lowbit(x) (x&(-x))
inline int read(){
    int x=0;char ch=getchar();
    while(ch<'0'||ch>'9'){ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x;
}
inline void add(int a,int p){
	for(;a<=n;a+=lowbit(a)) bit[a]+=p;
}
inline int qry(int a){
	int res=0;
	for(;a;a-=lowbit(a)){
		res+=bit[a];
	}
	return res;
}
inline void cons(){
	for(i=1;i<=n;++i){
		bit[i]+=a[i];
		bit[i+lowbit(i)]+=bit[i];
	}
}
struct query{
	int l,r,id;
} qrs[1000010];
bool cmp(const query& a,const query& b){
	return a.l<b.l;
}
int qrp;
int ans[1000010];
int main(){
	n=read();
	k=read();
	m=read();
	for(i=1;i<=n;++i) q[i]=read();
	for(i=n;i;--i) p[i]=c[q[i]],c[q[i]]=i;
	for(i=1;i<=k;++i) if(p[c[i]]) ++a[p[c[i]]];
	for(i=0;i<m;++i) qrs[i].l=read(),qrs[i].r=read(),qrs[i].id=i;
	std::sort(qrs,qrs+m,cmp);
	cons();
	qrp=0;
	for(i=1;i<=n;++i){
		if(qrs[qrp].l==i){
			j=qry(i-1);
			while(qrs[qrp].l==i&&qrp<m){
				ans[qrs[qrp].id]=qry(qrs[qrp].r)-j;
				++qrp;
			}
		}
		if(p[i]) add(p[i],-1);
		if(p[p[i]]) add(p[p[i]],1);
	}
	for(i=0;i<m;++i) printf("%d\n",ans[i]);
	return 0;
}
posted @ 2015-04-30 11:03  zball  阅读(389)  评论(0编辑  收藏  举报