您的位置:首页 > 其它

BZOJ1878(SDOI2009)[HH的项链]题解--莫队

2017-05-28 22:38 337 查看
【链接】

bzoj1878

【题目大意】

给你一个序列,让你求一段区间中不同数的个数。

【解题报告】

此题可以用莫队算法解,n比较小。(其实也可以用数状数组解,但本蒟蒻很懒就没写了。。)

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=50005,maxm=200005,maxv=1000005;
int n,m,sum,c[maxn],num[maxv],ans[maxm];
struct Interval
{
int L,R,sq,id;
bool operator < (const Interval &a) const{
return (sq<a.sq||(sq==a.sq&&R<a.R));
}
}a[maxm];
inline int Read()
{
int res=0;
char ch=getchar();
while (ch<'0'||ch>'9') ch=getchar();
while (ch>='0'&&ch<='9') res=res*10+ch-48,ch=getchar();
return res;
}
void Updata(int x,int p)
{
if (!num[c[x]]) sum++;
num[c[x]]+=p;
if (!num[c[x]]) sum--;
}
int main()
{
n=Read();
for (int i=1; i<=n; i++) c[i]=Read();
m=Read();
for (int i=1,k=sqrt(n); i<=m; i++)
{
a[i].L=Read(); a[i].R=Read();
a[i].sq=(a[i].L-1)/k+1; a[i].id=i;
}
sort(a+1,a+1+m);
memset(num,0,sizeof(num)); sum=0;
for (int i=a[1].L; i<=a[1].R; i++)
if (!(num[c[i]]++)) sum++;
ans[a[1].id]=sum;
for (int i=2,L=a[1].L,R=a[1].R; i<=m; i++)
{
while (L<a[i].L) Updata(L++,-1);
while (L>a[i].L) Updata(--L,1);
while (R<a[i].R) Updata(++R,1);
while (R>a[i].R) Updata(R--,-1);
ans[a[i].id]=sum;
}
for (int i=1; i<=m; i++) printf("%d\n",ans[i]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: