D-query SPOJ - DQUERY 區間不同數的個數(離線樹狀數組)

Given a sequence of n numbers a1, a2, ..., an and a number of d-queries. A d-query is a pair (i, j) (1 ≤ i ≤ j ≤ n). For each d-query (i, j), you have to return the number of distinct elements in the subsequence ai, ai+1, ..., aj.

Input

  • Line 1: n (1 ≤ n ≤ 30000).
  • Line 2: n numbers a1, a2, ..., an (1 ≤ ai ≤ 106).
  • Line 3: q (1 ≤ q ≤ 200000), the number of d-queries.
  • In the next q lines, each line contains 2 numbers i, j representing a d-query (1 ≤ i ≤ j ≤ n).

Output

  • For each d-query (i, j), print the number of distinct elements in the subsequence ai, ai+1, ..., aj in a single line.

     

Example

Input
5
1 1 2 1 3
3
1 5
2 4
3 5

Output
3
2
3 

題目大意:給你一個長度爲n的序列,接着M次詢問,每次詢問該區間有多少個不同的數。

。。。這題離線之後就可以直接用樹狀數組來完成,就不需要主席樹了。離線之後我們將區間按右端點最小值排序。

接下來我們從1枚舉到n,並將每個位置i單點更新,一旦碰到枚舉變量的值爲某個區間的右端點時就求和一次。但是如果在這之前a[i]已經出現過了,那麼我們應該將之前出現a[i]的位置放空,然後再更新i,那麼我們這樣就可以保證每個數只出現一次了。而每次有重複出現元素的時候之所以可以刪去前面的數是因爲如果前面的位置如果屬於區間x,那麼後面再次出現的這個元素也一定會屬於x,也就是說前面的那些重複元素是無用的,可以直接刪去。

以下是AC代碼:

#include <bits/stdc++.h>
using namespace std;

const int mac=3e4+10;
const int maxn=2e5+10;

int n,a[mac],b[mac],vis[mac];
int tree[mac],ans[maxn];

struct node
{
    int l,r,id;
    bool operator <(const node &a)const{
        return r<a.r;
    }
}c[maxn];

int lowbit(int x){return x&-x;}

void update(int pos,int val)
{
    while (pos<=n){
        tree[pos]+=val;
        pos+=lowbit(pos);
    }
}

int query(int l,int r)
{
    int sumr=0,suml=0;
    for (int i=r; i>0; i-=lowbit(i)) sumr+=tree[i];
    for (int i=l-1; i>0; i-=lowbit(i)) suml+=tree[i];
    return sumr-suml;
}

int main()
{
    int m;
    scanf ("%d",&n);
    for (int i=1; i<=n; i++) 
        scanf ("%d",&a[i]),b[i]=a[i];
    sort(b+1,b+1+n);
    int numb=unique(b+1,b+1+n)-b-1;
    for (int i=1; i<=n; i++) 
        a[i]=lower_bound(b+1,b+1+numb,a[i])-b;//其實這題的a[i]比較小不太需要離散化
    scanf ("%d",&m);
    for (int i=1; i<=m; i++){
        int l,r;
        scanf ("%d%d",&l,&r);
        c[i].l=l;c[i].r=r;
        c[i].id=i;
    }
    sort(c+1,c+1+m);
    int j=1;
    for (int i=1; i<=n; i++){
        if (vis[a[i]]) update(vis[a[i]],-1);
        update(i,1);
        while (j<=m && c[j].r==i){
            ans[c[j].id]=query(c[j].l,c[j].r);
            j++;
        }
        vis[a[i]]=i;
    }
    for (int i=1; i<=m; i++)
        printf ("%d\n",ans[i]);
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章