ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2492. HH的项链

2022-08-19 02:03:24  阅读:144  来源: 互联网

标签:cnt le int 复杂度 2492 len HH 项链


题目链接

2492. HH的项链

HH 有一串由各种漂亮的贝壳组成的项链。

HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义。

HH 不断地收集新的贝壳,因此他的项链变得越来越长。

有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同的贝壳?

这个问题很难回答,因为项链实在是太长了。

于是,他只好求助睿智的你,来解决这个问题。

输入格式

第一行:一个整数 \(N\),表示项链的长度。

第二行:\(N\) 个整数,表示依次表示项链中贝壳的编号(编号为 \(0\) 到 \(1000000\) 之间的整数)。

第三行:一个整数 \(M\),表示 HH 询问的个数。

接下来 \(M\) 行:每行两个整数,\(L\) 和 \(R\),表示询问的区间。

输出格式

\(M\) 行,每行一个整数,依次表示询问对应的答案。

数据范围

\(1 \le N \le 50000\),
\(1 \le M \le 2 \times 10^5\),
\(1 \le L \le R \le N\)

输入样例:

6
1 2 3 4 3 5
3
1 2
3 5
2 6

输出样例:

2
2
4

解题思路

莫队

莫队是一种离线做法,核心思想是分块+暴力

先考虑暴力做法:记录一个 \(cnt[x]\) 数组,表示当前区间 \(x\) 出现的次数,在两个区间转移时,即左右指针分别移动到对应区间的同时更新 \(cnt[x]\),同时更新答案
分块策略:将所有区间按左端点分块,同时块内的区间右端点排序再暴力求解

复杂度证明:假设块的大小为 \(len\),块内右端点由于有序,一个块内右指针移动的复杂度为 \(O(n)\),则总复杂度为 \(O(n\times \frac{n}{len})\),左指针对于每个块内的每个左指针移动的复杂度无论是在块内还是块间移动的复杂度都为 \(O(len)\),则总复杂度为 \(O(m\times len)\),令 \(n\times \frac{n}{len}=m\times len\),即 \(len=\sqrt{\frac{n^2}{m}}\),则:

  • 时间复杂度:\(n\sqrt{m}\)

代码

// Problem: HH的项链
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/2494/
// Memory Limit: 64 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}
const int N=2e5+5,M=5e4+5;
int n,m,a[M],len,cnt[1000005],res[N];
struct Q
{
	int id,l,r;
}q[N];
int get(int x)
{
	return x/len;
}
void add(int x,int &res)
{
	if(!cnt[x])res++;
	cnt[x]++;
}
void del(int x,int &res)
{
	cnt[x]--;
	if(!cnt[x])res--;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    scanf("%d",&m);
    len=max(1,int(sqrt((double)n*n/m)));
    for(int i=1;i<=m;i++)scanf("%d%d",&q[i].l,&q[i].r),q[i].id=i;
    sort(q+1,q+1+m,[](auto &a,auto &b){
    	int i=get(a.l),j=get(b.l);
    	if(i!=j)return i<j;
    	else if(i&1)return a.r<b.r;
    	return a.r>b.r;
    });
    for(int k=1,i=0,j=1,t=0;k<=m;k++)
    {
    	int l=q[k].l,r=q[k].r;
    	while(i<r)add(a[++i],t);
    	while(i>r)del(a[i--],t);
    	while(j<l)del(a[j++],t);
    	while(j>l)add(a[--j],t);
    	res[q[k].id]=t;
    }
    for(int i=1;i<=m;i++)printf("%d\n",res[i]);
    return 0;
}

标签:cnt,le,int,复杂度,2492,len,HH,项链
来源: https://www.cnblogs.com/zyyun/p/16600658.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有