캐주얼 작업
시퀀스에, 그래서 당신은 다른 수치의 숫자 [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;
}