BZOJ1878 [SDOI2009]HH的项链 树状数组 或 莫队
欢迎访问~原文出处——博客园-zhouzhendong
去博客园看该题解
题目传送门 - BZOJ1878
题意概括
给出一个长度为n的序列,用m次询问,问区间Li~Ri中有多少种不同的数。
0<=数值<=1000000,n<=50000,m<=200000
题解
本题有许多做法。
这里介绍树状数组和莫队,都是离线算法。
树状数组
我们把序列按照R从小到大排序。
然后从左往右走。
依次加入数字,当前的状态,比如说搞定了前i个数字。
对于第i+1个数字,我们要给它做一个标记,但是不可以重复,那么最优的方案就是把它之前的那个位置的+1标记删除,放到这里来。
于是对于搞定前i个数的时候,有且一定有对于某一个数值,如果它出现过,那么它的+1标记在最后出现的那个地方。
为什么可以?因为R是递增的!
然后就是维护一个点修改和区间和的东西了。秒选树状数组。
莫队
莫队就是最裸的莫队。
先把1~n的区间尽量平均的分成sqrt(n)块。
把所有的询问以L所在的块为第一关键字升序,R为第二关键字升序排序。
然后就是大暴力。
朴素的写法有点长。
但是压缩之后短的无厘头……
代码
代码1 - 树状数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | #include <cstring> #include <cstdio> #include <algorithm> #include <cstdlib> #include <cmath> using namespace std; const int N=50000+5,M=200000+5,V=1000000+5; int n,m,a[N],c[N],pos[V]; struct Query{ int L,R,bh,ans; bool operator < ( const Query x) const { return R<x.R; } }q[M]; bool cmpbh(Query a,Query b){ return a.bh<b.bh; } int lowbit( int x){ return x&-x; } void add( int x, int d){ if (!x) return ; for (;x<=n;x+=lowbit(x)) c[x]+=d; } int sum( int x){ int ans=0; for (;x>0;x-=lowbit(x)) ans+=c[x]; return ans; } int main(){ scanf ( "%d" ,&n); for ( int i=1;i<=n;i++) scanf ( "%d" ,&a[i]); scanf ( "%d" ,&m); for ( int i=1;i<=m;i++){ scanf ( "%d%d" ,&q[i].L,&q[i].R); q[i].bh=i; } sort(q+1,q+m+1); memset (pos,0, sizeof pos); memset (c,0, sizeof c); for ( int i=1,j=0;i<=m;i++){ while (j<q[i].R){ j++; add(pos[a[j]],-1); pos[a[j]]=j; add(pos[a[j]],1); } q[i].ans=sum(q[i].R)-sum(q[i].L-1); } sort(q+1,q+m+1,cmpbh); for ( int i=1;i<=m;i++) printf ( "%d\n" ,q[i].ans); return 0; } |
代码2 - 莫队
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | #include <cstring> #include <cstdio> #include <algorithm> #include <cstdlib> #include <cmath> using namespace std; const int N=50000+5,M=200000+5,V=1000000+5; int n,m,size,a[N],cnt[V]; struct Query{ int L,R,bh,ans; }q[M]; bool cmpmd(Query a,Query b){ int k1=a.L/size,k2=b.L/size; if (k1!=k2) return k1<k2; return a.R<b.R; } bool cmpbh(Query a,Query b){ return a.bh<b.bh; } int main(){ scanf ( "%d" ,&n); for ( int i=1;i<=n;i++) scanf ( "%d" ,&a[i]); scanf ( "%d" ,&m); for ( int i=1;i<=m;i++){ scanf ( "%d%d" ,&q[i].L,&q[i].R); q[i].bh=i; } size= sqrt (n)+0.5; memset (cnt,0, sizeof cnt); sort(q+1,q+m+1,cmpmd); for ( int i=1,tot=0,L=1,R=0;i<=m;i++){ while (R<q[i].R){ R++; if (cnt[a[R]]==0) tot++; cnt[a[R]]++; } while (L>q[i].L){ L--; if (cnt[a[L]]==0) tot++; cnt[a[L]]++; } while (R>q[i].R){ cnt[a[R]]--; if (cnt[a[R]]==0) tot--; R--; } while (L<q[i].L){ cnt[a[L]]--; if (cnt[a[L]]==0) tot--; L++; } q[i].ans=tot; } sort(q+1,q+m+1,cmpbh); for ( int i=1;i<=m;i++) printf ( "%d\n" ,q[i].ans); return 0; } |
代码3 - 莫队+代码压缩
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | #include <cstring> #include <cstdio> #include <algorithm> #include <cstdlib> #include <cmath> using namespace std; const int N=50000+5,M=200000+5,V=1000000+5; int n,m,size,a[N],cnt[V]; struct Query{ int L,R,bh,ans; }q[M]; bool cmpmd(Query a,Query b){ int k1=a.L/size,k2=b.L/size; if (k1!=k2) return k1<k2; return a.R<b.R; } bool cmpbh(Query a,Query b){ return a.bh<b.bh; } int main(){ scanf ( "%d" ,&n); for ( int i=1;i<=n;i++) scanf ( "%d" ,&a[i]); scanf ( "%d" ,&m); for ( int i=1;i<=m;i++) scanf ( "%d%d" ,&q[i].L,&q[i].R),q[i].bh=i; size= sqrt (n)+0.5; memset (cnt,0, sizeof cnt); sort(q+1,q+m+1,cmpmd); for ( int i=1,tot=0,L=1,R=0;i<=m;i++){ while (R<q[i].R) tot+=cnt[a[++R]]++==0; while (L>q[i].L) tot+=cnt[a[--L]]++==0; while (R>q[i].R) tot-=--cnt[a[R--]]==0; while (L<q[i].L) tot-=--cnt[a[L++]]==0; q[i].ans=tot; } sort(q+1,q+m+1,cmpbh); for ( int i=1;i<=m;i++) printf ( "%d\n" ,q[i].ans); return 0; } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
· .NET 适配 HarmonyOS 进展
· 如何给本地部署的DeepSeek投喂数据,让他更懂你
· 超详细,DeepSeek 接入PyCharm实现AI编程!(支持本地部署DeepSeek及官方Dee
· 用 DeepSeek 给对象做个网站,她一定感动坏了
· .NET 8.0 + Linux 香橙派,实现高效的 IoT 数据采集与控制解决方案
· .NET中 泛型 + 依赖注入 的实现与应用