[BZOJ1878][SDOI2009]HH的项链解题报告

HH有一串由各种漂亮的贝壳组成的项链。HH相信不同的贝壳会带来好运,所以每次散步 完后,他都会随意取出一
段贝壳,思考它们所表达的含义。HH不断地收集新的贝壳,因此他的项链变得越来越长。有一天,他突然提出了一
个问题:某一段贝壳中,包含了多少种不同的贝壳?这个问题很难回答。。。因为项链实在是太长了。于是,他只
好求助睿智的你,来解决这个问题。
Input
第一行:一个整数N,表示项链的长度。 
第二行:N个整数,表示依次表示项链中贝壳的编号(编号为0到1000000之间的整数)。 
第三行:一个整数M,表示HH询问的个数。 
接下来M行:每行两个整数,L和R(1 ≤ L ≤ R ≤ N),表示询问的区间。
N ≤ 50000,M ≤ 200000。
Output

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

Sample Input
6
1 2 3 4 3 5
3
1 2
3 5
2 6

Sample Output

2

2

4

看到题目,首先确定这是区间问题。然后考虑到不满足区间加减,于是考虑变形。

我们从左到右维护前缀和,表示在此前有多少个不同的。这个很容易用树状数组实现。

然后考虑到我们从左到右维护时,问题不一定从左到右,但这时离线的,我们就能排序后继续做。

维护到第i位,对于每一个r在i上的询问,它的答案等于Sr-S(l-1).

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
inline void read(int &x)
{
    x=0;int f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    x*=f;
}
int N,Q,arr[500005]; 
int tree[500005];
int ahead[1000005];
int ans[500005];
struct question{
    int l,r,num;
}que[500005];
int lowbit(int x)
{
    return x&(-x);
}
void update(int x,int p)
{
    for(int i=p;i<=N;i+=lowbit(i))
        tree[i]+=x;
}
int query(int p)
{
    int ans=0;
    for(int i=p;i>0;i-=lowbit(i))
        ans+=tree[i];
    return ans; 
}
bool cmp1(question a,question b)
{
    return a.r<b.r;
}
bool cmp2(question a,question b)
{
    return a.num<b.num;
}
int main()
{
    read(N);
    for(int i=1;i<=N;i++)
        read(arr[i]);
    read(Q);
    for(int i=1;i<=Q;i++)
    {
        read(que[i].l);
        read(que[i].r);
        que[i].num=i;
    } 
    sort(que+1,que+Q+1,cmp1);
    int ques=1;
    for(int i=1;i<=N;i++)
    {
        if(!ahead[arr[i]]){
            ahead[arr[i]]=i;
            update(1,i);
        }
        else{
            update(-1,ahead[arr[i]]);
            update(1,i);
            ahead[arr[i]]=i;
        }
        while(ques<=Q){
            if(que[ques].r==i)
            {
                ans[que[ques].num]=query(que[ques].r)-query(que[ques].l-1);
                ques++;
            }        
            else
                break;
        }
    }
    for(int i=1;i<=Q;i++)
        printf("%d\n",ans[i]);
}

 

posted @ 2018-08-28 17:26  溡沭  阅读(122)  评论(0编辑  收藏  举报