您的位置:首页 > 其它

bzoj 1878(离线+树状数组)

2016-03-15 19:11 190 查看

1878: [SDOI2009]HH的项链

Time Limit: 4 Sec Memory Limit: 64 MB

Submit: 2696 Solved: 1353

[Submit][Status][Discuss]

Description

HH有一串由各种漂亮的贝壳组成的项链。HH相信不同的贝壳会带来好运,所以每次散步 完后,他都会随意取出一段贝壳,思考它们所表达的含义。HH不断地收集新的贝壳,因此, 他的项链变得越来越长。有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同 的贝壳?这个问题很难回答。。。因为项链实在是太长了。于是,他只好求助睿智的你,来解 决这个问题。

Input

第一行:一个整数N,表示项链的长度。 第二行:N个整数,表示依次表示项链中贝壳的编号(编号为0到1000000之间的整数)。 第三行:一个整数M,表示HH询问的个数。 接下来M行:每行两个整数,L和R(1 ≤ L ≤ R ≤ N),表示询问的区间。

Output

M行,每行一个整数,依次表示询问对应的答案。

Sample Input

6

1 2 3 4 3 5

3

1 2

3 5

2 6

Sample Output

2

2

4

HINT

对于20%的数据,N ≤ 100,M ≤ 1000;

对于40%的数据,N ≤ 3000,M ≤ 200000;

对于100%的数据,N ≤ 50000,M ≤ 200000。

解题思路:首先想到线段树,但是空间太小,想来想去,只能离线,然后树状数组,

记入下每个数在序列中对应的所有位置。



对讯问按照起点排序。用tail来当做原数组的指针。如果tail<start[i]就要剪掉之间

所有数,在维护后一个同样数所在的位置(树状数组)。

#include<cstdio>

#include<cstring>

#include<algorithm>

#include<iostream>

using namespace std;

int n,ans,q,len;

int a[51000],messi[51000];

struct ss

{

int x,y,dui;

}g[210000];

int zhong[1100001],to[51000],h[1100001],next[51000];

int sum[210000];

inline int read()

{

char y; int x=0,f=1; y=getchar();

while (y<'0' || y>'9') {if (y=='-') f=-1; y=getchar();}

while (y>='0' && y<='9') {x=x*10+int(y)-48; y=getchar();}

return f*x;

}

bool cmp(ss xg,ss yg)

{

return xg.x<yg.x;

}

void add(int now,int zhi)

{

while (now<=n)

{

messi[now]+=zhi;

now+=now&-now;

}

}

int query(int o)

{

int sum=0;

while (o>0)

{

sum+=messi[o];

o-=o&-o;

}

return sum;

}

void insert(int x,int y)

{

++len;

to[len]=y; next[len]=h[x]; h[x]=len;

}

int main()

{

n=read();

for (int i=1;i<=n;++i)

{

a[i]=read();

if (zhong[a[i]]==0)

{

add(i,1);

}

++zhong[a[i]];

}

for (int i=n;i>=1;--i)

{

insert(a[i],i);

}

q=read();

for (int i=1;i<=q;++i)

{

g[i].x=read(); g[i].y=read(); g[i].dui=i;

}

sort(g+1,g+q+1,cmp);

int tail=1;

for (int i=1;i<=q;++i)

{

while (tail<g[i].x)

{

add(tail,-1);

h[a[tail]]=next[h[a[tail]]];

if (h[a[tail]]!=0)

{

add(to[h[a[tail]]],1);

}

++tail;

}

sum[g[i].dui]=query(g[i].y)-query(g[i].x-1);

}

for (int i=1;i<=q;++i)

{

printf("%d\n",sum[i]);

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: