2492. HH的项链

题目链接

2492. HH的项链

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

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

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

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

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

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

输入格式

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

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

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

接下来 M 行:每行两个整数,LR,表示询问的区间。

输出格式

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

数据范围

1N50000,
1M2×105,
1LRN

输入样例:

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×nlen),左指针对于每个块内的每个左指针移动的复杂度无论是在块内还是块间移动的复杂度都为 O(len),则总复杂度为 O(m×len),令 n×nlen=m×len,即 len=n2m,则:

  • 时间复杂度:nm

代码

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

__EOF__

本文作者acwing_zyy
本文链接https://www.cnblogs.com/zyyun/p/16600658.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zyy2001  阅读(48)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示