版权声明: https://blog.csdn.net/nucleare/article/details/88969864
D-query
English | Vietnamese |
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
题意:求区间种类数
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
#include <cmath>
using namespace std;
const int N = 3e4 + 7;
const int M = 1e6 + 7;
int a[N];
int in[M], sum; //!标记!、种类
int ans[200007]; //答案
struct Q {
int l, r, b, id; //l,r为询问区间,b为block即所属的块,id为询问的下标(先后
bool operator< (const Q &a) const {
if (b == a.b) return r < a.r; //b!!!
return b < a.b;
}
} qq[200007];
//up and down 要根据题目要求更改
void up(int x) {
if (in[a[x]] == 0) ++sum;
++in[a[x]];
}
void down(int x) {
--in[a[x]];
if (in[a[x]] == 0) --sum;
}
int main() {
int n, block;
while (~scanf ("%d", &n)) {
memset(in, 0, sizeof(in));
block = sqrt(n*1.0); //分块
for (int i = 1; i <= n; ++i) {
scanf ("%d", &a[i]);
}
int q;
scanf ("%d", &q);
for (int i = 1; i <= q; ++i) {
scanf ("%d %d", &qq[i].l, &qq[i].r);
qq[i].id = i, qq[i].b = qq[i].l / block;
}
sort(qq+1, qq+q+1);
int l = 1, r = 0; //初始的区间
// l为什么是1,因为++r时会把l的给加了, 是0的话会重复
sum = 0;
for (int i = 1; i <= q; ++i) {
int ll = qq[i].l;
int rr = qq[i].r;
//扩大
while (r < rr) ++r, up(r);
while (l > ll) --l, up(l);
//缩小
while (r > rr) down(r), --r; //顺序
while (l < ll) down(l), ++l;
//记录答案
ans[qq[i].id] = sum;
}
for (int i = 1; i <= q; ++i) {
printf ("%d\n", ans[i]);
}
}
return 0;
}