2492. HH的项链
题目:
HH 有一串由各种漂亮的贝壳组成的项链。
HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义。
HH 不断地收集新的贝壳,因此他的项链变得越来越长。
有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同的贝壳?
这个问题很难回答,因为项链实在是太长了。
于是,他只好求助睿智的你,来解决这个问题。
输入格式
第一行:一个整数 NN,表示项链的长度。
第二行:NN 个整数,表示依次表示项链中贝壳的编号(编号为 00 到 10000001000000 之间的整数)。
第三行:一个整数 MM,表示 HH 询问的个数。
接下来 MM 行:每行两个整数,LL 和 RR,表示询问的区间。
输出格式
MM 行,每行一个整数,依次表示询问对应的答案。
数据范围
1≤N≤500001≤N≤50000,
1≤M≤2×1051≤M≤2×105,
1≤L≤R≤N1≤L≤R≤N输入样例:
6 1 2 3 4 3 5 3 1 2 3 5 2 6输出样例:
2 2 4
代码:
#include <bits/stdc++.h> using namespace std; const int N = 50010, M = 200010, S = 1000010; int n, m, T; int w[N], ans[M]; struct Q{ int l, r, i, x, y; inline Q() {} inline Q(int l, int r, int i) : l(l), r(r), i(i) {x = l / T, y = r;} inline friend bool operator< (const Q &a, const Q &b) { return a.x == b.x ? (a.x & 1) ? a.y < b.y : a.y > b.y : a.x < b.x; } }q[M]; int cnt[S]; void add(int x, int& res) { //第一次出现,说明出现了新的贝壳,标记+1 if (!cnt[x]) res ++; cnt[x] ++; } void del(int x, int& res) { //将当前-1,如果-1为0,则贝壳种类-1 cnt[x] --; if (!cnt[x]) res --; } int main() { scanf("%d", &n); for (int i = 1; i <= n; i ++ ) scanf("%d", &w[i]); scanf("%d", &m); T = sqrt((double) n * n / m); for (int i = 0; i < m; i ++ ) { int l, r; scanf("%d%d", &l, &r); q[i] = {l, r, i}; } sort(q, q + m); // for (int i = 0; i < m; i ++ ) // printf("[l = %d, r = %d]\n", q[i].l, q[i].r); for (int k = 0, l = 1, r = 0, res = 0; k < m; k ++ ) { while (l < q[k].l) del(w[l ++ ], res); while (l > q[k].l) add(w[-- l ], res); while (r < q[k].r) add(w[++ r ], res); while (r > q[k].r) del(w[r -- ], res); ans[q[k].i] = res; } for (int i = 0; i < m; i ++ ) printf("%d\n", ans[i]); return 0; }