Solution: bzoj1878: [SDOI2009] HH's necklace

Description

HH has a necklace of various beautiful shells. HH believes that different shells bring good luck, so after each walk, he will take out one at random.
segment the shells and think about what they mean. HH is constantly collecting new shells, so his necklaces are getting longer and longer. One day, he suddenly proposed a
Question: How many different kinds of shells are contained in a certain section of shells? This question is difficult to answer. . . Because the necklace is really too long. So he only
I would like to ask you, wise man, to solve this problem.

Input

The first line: an integer N, representing the length of the necklace. 
The second line: N integers, representing the serial numbers of the shells in the necklace (the numbers are integers between 0 and 1000000). 
The third line: an integer M, indicating the number of HH queries. 
Next M lines: each line has two integers, L and R (1 ≤ L ≤ R ≤ N), indicating the interval of the query.
N ≤ 50000,M ≤ 200000。

Output

M lines, each with an integer, in turn represent the corresponding answers to the query.

Sample Input

6
1 2 3 4 3 5
3
1 2
3 5
2 6

Sample Output

2
2
4
 
answer:
 
Offline query + tree array
In fact, the tree-like array is used to maintain the interval different numbers. Consider recording the number of distinct numbers in the first i numbers, and for the query q(l,r), just like the prefix sum, use num[r]-num[l-1] to calculate the answer.
In fact, this algorithm is not correct, such as 1 2 3 3 5, num[4]=3, num[5]=4, num[5]-num[4-1]=1, but q(4,5 ) The answer should be 2.
It is not difficult to find that the bug of this algorithm is that num[i] records [1, i], because 3 has already appeared before. Therefore, when querying q(l, r), if [l, r] has a number that has appeared in [1, l], it will be undercounted. Therefore, a next array can be introduced, and next[i] records the position of the next occurrence of the number represented by the current position i. When the i-th bit is processed, the position pointed to by next[i] is modified to the full prefix sum, so that, Can be calculated with num[r]-num[i-1]
Offline the query and sort it according to the left boundary from small to large, use pos[i] to represent the position of the first occurrence of number i, and then process the query in order: scan the entire interval from left to right, and use a tree for each number. The array modifies the prefix sum of its next until it hits the left boundary of a query, then computes the answer as num[r]-num[i-1].
Can be understood by my combined code.
#include<bits/stdc++.h>
using namespace std;
struct question{
    int l,r,ans,idx;
}q[200005];
int n,m,mx=0;
int necklace[50005],pos[1000005],nextx[50005],node[50005];
int lowbit(int a)
{
    return a&(-a);
}
int add(int k,int val)
{
    for(;k<=n;k+=lowbit(k))
        node[k]+=val;
}
int ask(int k)
{
    int sum=0;
    for(;k>0;k-=lowbit(k))
        sum+=node[k];
    return sum;    
}
int maxn(int a,int b)
{
    return a>b?a:b;
}
bool cmp1(question a,question b)
{
    return a.l<b.l;
}
bool cmp2(question a,question b)
{
    return a.idx<b.idx;
}
intmain ()
{
    memset(pos,0,sizeof(pos));
    memset(nextx,0,sizeof(nextx));
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        {
            scanf("%d",&necklace[i]);
            mx=maxn(mx,necklace[i]);
        }
    for(int i=n;i>=1;i--)
        {
            nextx[i]=pos[necklace[i]];
            pos[necklace[i]]=i;
        }
    for(int i=1;i<=mx;i++)
        if(pos[i])
           add(pos[i],1);
    scanf("%d",&m);       
    for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&q[i].l,&q[i].r);
            q[i].idx=i;
        }
    sort(q+1,q+1+m,cmp1);
    int L=1;
    for(int i=1;i<=m;i++)
        {
            while(L<q[i].l)
                  {
                       if(nextx[L])
                          add(nextx[L],1);
                       L++;         
                  }
            q[i].ans=ask(q[i].r)-ask(q[i].l-1);      
        }
    sort(q+1,q+1+m,cmp2);
    for(int i=1;i<=m;i++)
        printf("%d\n",q[i].ans);         
}
View Code

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325116958&siteId=291194637