[BZOJ 1878]HH的项链(树状数组+离线)

来源:互联网 发布:天猫国际和淘宝全球购 编辑:程序博客网 时间:2024/05/18 23:52

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

Solution


代码调了很多遍,RE,发现是head数组开小了,好气哦
把询问按照右端点从大到小排序,从右往左扫。若在当前的右端点以内,某个数是第一次出现,则此处种类+1,用树状数组维护
head[i]记录i从右往左第一次出现的位置,next[i]是i这个个位置上的数字下一次出现的位置

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int n,m,a[50005],head[1000005],next[50005],c[50005],res[200005];struct Node{    int l,r,ID;}q[200005];bool cmp(Node a,Node b){    return a.r>b.r;}int lowbit(int x){    return x&(-x);}void add(int pos,int x){    while(pos<=n)    {        c[pos]+=x;        pos+=lowbit(pos);    }}int query(int pos){    int res=0;    while(pos>0)    {        res+=c[pos];        pos-=lowbit(pos);    }    return res;}int main(){    scanf("%d",&n);    int x;    for(int i=1;i<=n;i++)    {        scanf("%d",&a[i]);        if(!head[a[i]])        {            head[a[i]]=i;        }        else         {            next[i]=head[a[i]];            head[a[i]]=i;        }    }    scanf("%d",&m);    for(int i=1;i<=m;i++)    {        scanf("%d%d",&q[i].l,&q[i].r);        q[i].ID=i;    }    sort(q+1,q+1+m,cmp);    int j=n,k=n;    while(j>=1)    {        if(head[a[j]]==j)add(j,1);        j--;    }    for(int i=1;i<=m;i++)    {        while(k>q[i].r)        {            head[a[k]]=next[k];            if(next[k])            add(next[k],1);            k--;        }        res[q[i].ID]=query(q[i].r)-query(q[i].l-1);    }    for(int i=1;i<=m;i++)    printf("%d\n",res[i]);    return 0;}
0 0
原创粉丝点击