AcWing算法进阶课 莫队

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;
}

  

 

上一篇:Python Cats vs Dogs 分类


下一篇:HH去散步