간격에 다른 번호의 수를 찾는 (펜윅 나무)

캐주얼 작업

시퀀스에, 그래서 당신은 다른 수치의 숫자 [L, R]을 찾아 낸다

기입

입력 없음, 시퀀스는 N 개의 디지털 함유 하였다

쿼리 간격을 나타내는 정수 두 다음에 Q를 입력

수출

질의 Q의 결과

견본

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

Output
3
2
3 

사고

트리 어레이를 기록하는 i 번째 자리에서 상이한 수의 시퀀스 번호 앞에.

간격 시작 스캔 왼쪽에서 쿼리 :

1. 数字首次出现时,当前位置加一,且用map记录下当前数字出现的位置
2. 数字非首次出现时,当前位置加一,但是上次出现的位置要减一

쿼리 간격 후 getsum(r) - getsum(l - 1)답변입니다.

두 번째 경우를 수행 할 때 전체 시퀀스 스캔 프로세스가 완료되면 확인해야하므로 위의 과정에 대해 신중하게 생각, 이전의 결과는 파괴됩니다.

주의를 기울 그래서 :

1. 按照查询区间的右端点值进行排序(当前的会破坏前面的结果)
2. 保证整个序列中的元素仅扫描一次,即代码中的`pre = query[i].r + 1;`而不是`pre = query[i + 1].l;`

코드

#include <stdio.h>
#include <string>
#include <stdlib.h>
#include <iostream>
#include <vector>
#include <string.h>
#include <algorithm>
#include <map>
using namespace std;
const int maxn = 10000;
int n = 0, q = 0;

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



int v[maxn], sum[maxn], ans[maxn];

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

void change(int i, int a){
    while(i <= n){
        sum[i] += a;
        i += lowbit(i);
    }
}

int getsum(int i){
    int sum_t = 0;
    while(i > 0){
        sum_t += sum[i];
        i -= lowbit(i);
    }
    return sum_t;
}

int main() {
    
    while(~scanf("%d", &n)){
        memset(v, 0, sizeof(v));
        memset(sum, 0, sizeof(sum));
        memset(ans, 0, sizeof(ans));
        
        int t = 0;
        for(int i = 1; i <= n; i++){
            scanf("%d", &v[i]);
        }
        scanf("%d", &q);
        for(int i = 1; i <= q; i++){
            scanf("%d%d", &query[i].l, &query[i].r);
            query[i].id = i;
        }
        sort(query + 1, query + q + 1);
        
        int pre = 1;
        map<int, int> mymap;
        for(int i = 1; i <= q; i++){
            for(int j = pre; j <= query[i].r; j++){
                //已存在 
                if(mymap[v[j]]){
                    change(mymap[v[j]], -1);
                }
                mymap[v[j]] = j;
                change(j, 1);
            }
            pre = query[i].r + 1;
            ans[query[i].id] = getsum(query[i].r) - getsum(query[i].l - 1);
        }
        
        for(int i = 1; i <= q; i++){
            cout << ans[i] << endl;
        }
    }
    return 0;
}

추천

출처www.cnblogs.com/woxiaosade/p/12305677.html