·述大意:

       多个区间询问,询问[l,r]中颜色的种类数。可以单点修改颜色。

·分析:

莫队可以修改?那不是爆炸了吗。

这类爆炸的问题被称为带修莫队(可持久化莫队)。

按照美妙类比思想,可以引入一个“修改时间”,表示当前询问是发生在前Time个修改操作后的。也就是说,在进行莫队算法时,看看当前的询问和时间指针(第三个指针,别忘了l,r)是否相符,然后进行时光倒流或者时光推移操作来保证答案正确性。

·Sort的构造。仅靠原来的sort关键字会使得枚举每个询问都可能因为时间指针移动的缘故要移动n次,总共就n2次,那还不如写暴力。

·为了防止这样的事情发生,再加入第三关键字Tim:

·如何理解时间复杂度?

首先,R和Tim的关系就像L和R的关系一样:只有在前者处于同块时,后者才会得到排序的恩赐,否则sort会去满足前者,使得后者开始乱跳。

依旧像上文那样:枚举m个答案,就一个m了。设分块大小为unit。

分类讨论:

①对于l指针,依旧是O(unit*n)

②对于r指针,依旧是O(n*n/unit)

③对于T指针(即Time):

    类比r时间复杂度的计算。我们要寻找有多少个单调段(一个单调段下来最多移动n次)。上文提到,当且仅当两个询问l在同块,r也在同块时,才会对可怜的Tim进行排序。局势明朗。对于每一个l的块,里面r最坏情况下占据了所有的块,所以最坏情况下:有n/unit个l的块,每个l的块中会有n/unit个r的块,此时,在一个r块里,就会出现有序的Tim。所以Tim的单调段个数为:(n/unit)*(n/unit)。每个单调段最多移动n次。

所以:O((n/unit)2*n)

三个指针汇总:O(unit*n+n2/unit+(n/unit)2*n)

例题如下:

传送门: 2120: 数颜色

个人代码:

第一次修改:莫队必须分块。d代码就不做调整了   文章末尾有分块实现的代码

#include<bits/stdc++.h>
using namespace std;
struct Query{int l,r,tim,id;}q[10006];//存放查询,查询的区间 lr 查询时的时间,第几个查询
struct update{int pos,New,Old;}u[10005];//存放修改,修改的位置,修改成什么,修改之前是什么
int n,m,xx,yy,t,color[100005],s[10005],Ans,Time,now[10005],ans[100005],l=1,r=0,T;
//n是区间长度,m是操作次数,xx和yy是每次操作用的,t是查询计数器,color是当前答案区间内的颜色,s是存放数据的,Ans是当前答案
//Time是修改计数器(当前时间) ,now是当前的颜色,ans是答案数组, lr是上一次查询的区间初始化为10,T是上一次查询的时间
char c;//问题类型是什么
bool cmp(Query a,Query b){return a.l==b.l?(a.r==b.r?a.tim<b.tim:a.r<b.r):a.l<b.l;}
void revise(int x,int d){color[x]+=d;//为答案数组里改变这个颜色的数量 if(d<0)Ans-=color[x]==0;//如果是从有到无 else Ans+=color[x]==1;//如果是从无到有
}
void going(int x,int d){if(l<=x&&x<=r)revise(d,1),revise(s[x],-1);//如果是上一次区间内的,才修改答案(Ans是答案,用来不断修改的答案) s[x]=d;//修改这个值
}
int main(){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){scanf("%d",&s[i]); now[i]=s[i];}//输入 for(int i=1;i<=m;i++){scanf(" %c%d%d",&c,&xx,&yy);if(c=='Q')q[++t]=(Query){xx,yy,Time,t};//t是计数器,也就是查询xx-yy 在Time时的情况 else u[++Time]=(update){xx,yy,now[xx]},now[xx]=yy;//这一次修改之前x的颜色是now[xx],修改成yy,并将now更新 }sort(q+1,q+t+1,cmp);//根据左节点 右节点 时间戳进行排序 for(int i=1;i<=t;i++){while(T<q[i].tim)going(u[T+1].pos,u[T+1].New),T++;//如果当下是过去,去未来 while(T>q[i].tim)going(u[T].pos,u[T].Old),T--; //如果当下是未来  回到过去while(l<q[i].l)revise(s[l],-1),l++;//当前l小于区间 while(l>q[i].l)revise(s[l-1],1),l--;//。。 。 while(r<q[i].r)revise(s[r+1],1),r++;//。。 。 while(r>q[i].r)revise(s[r],-1),r--;//。。。 ans[q[i].id]=Ans;//存放的是答案 }for(int i=1;i<=t;i++)printf("%d\n",ans[i]);return 0;
}

大佬代码:

#include<stdio.h>
#include<algorithm>
#include<math.h>
#define go(i,a,b) for(int i=a;i<=b;i++)
using namespace std;const int N=10003;
struct Query{int l,r,Tim,ID;}q[N];
struct Change{int pos,New,Old;}c[N];
int n,m,s[N],color[N*100],t,Time,now[N],unit,Be[N],ans[N],Ans,l=1,r,T;
bool cmp(Query a,Query b)
{return Be[a.l]==Be[b.l]?(Be[a.r]==Be[b.r]?a.Tim<b.Tim:a.r<b.r):a.l<b.l;
}
void revise(int x,int d){color[x]+=d;if(d>0)Ans+=color[x]==1;if(d<0)Ans-=color[x]==0;}
void going(int x,int d){if(l<=x&&x<=r)revise(d,1),revise(s[x],-1);s[x]=d;}
int main(){scanf("%d%d",&n,&m);unit=pow(n,0.666666);go(i,1,n)scanf("%d",&s[i]),now[i]=s[i],Be[i]=i/unit+1;go(i,1,m){char sign;int x,y;scanf(" %c %d%d",&sign,&x,&y);if(sign=='Q')q[++t]=(Query){x,y,Time,t};if(sign=='R')c[++Time]=(Change){x,y,now[x]},now[x]=y;}sort(q+1,q+t+1,cmp);go(i,1,t){while(T<q[i].Tim)going(c[T+1].pos,c[T+1].New),T++;while(T>q[i].Tim)going(c[T].pos,c[T].Old),T--;while(l<q[i].l)revise(s[l],-1),l++;while(l>q[i].l)revise(s[l-1],1),l--;while(r<q[i].r)revise(s[r+1],1),r++;while(r>q[i].r)revise(s[r],-1),r--;ans[q[i].ID]=Ans;}go(i,1,t)printf("%d\n",ans[i]);return 0;
}//Paul_Guderian

大佬博客:https://www.cnblogs.com/Paul-Guderian/p/6933799.html

莫队入门例题之持久化莫队:2120: 数颜色相关推荐

  1. 2120: 数颜色(带修莫队)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2120 2120: 数颜色 Time Limit: 6 Sec  Memory Limit ...

  2. 莫队入门例题:2038: [2009国家集训队]小Z的袜子(hose)

    题目大意: Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命-- 具体来说, ...

  3. 普通、带修(可持久化)莫队算法入门例题详解

    目录 [莫队算法] [普通莫队] [代码] [题面] [带修莫队] [代码] [题面] [总结] [莫队算法] 参考大米饼的莫队算法 ,目前的题型概括为三种:普通莫队,带修莫队以及树形莫队. [普通莫 ...

  4. BZOJ2120 数颜色 【带修改莫队】

    2120: 数颜色 Time Limit: 6 Sec  Memory Limit: 259 MB Submit: 6579  Solved: 2625 [Submit][Status][Discus ...

  5. 【莫队/树上莫队/回滚莫队】原理详解及例题:小B的询问(普通莫队),Count on a tree II(树上莫队),kangaroos(回滚莫队)

    文章目录 问题引入 介绍莫队算法及其实现过程 时间复杂度 莫队算法适用范围 莫队奇偶优化 普通莫队:小B的询问 树上莫队:SP10707 COT2 - Count on a tree II 回滚莫队: ...

  6. HYSBZ - 2038 小Z的袜子(hose) (莫队入门)

    题目: 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命-- 具体来说,小Z把这N只袜子从1到N编号 ...

  7. 红队 入门_我穿越网络安全红队的硕士证书的旅程

    红队 入门 August 26 BY Kaavyaa.A 8月26日,Kaavyaa.A This is my personal experience with the one-of-a-kind p ...

  8. c语言基础编程题讲解,C语言入门例题讲解

    C语言入门例题讲解 C语言是一门通用计算机编程语言,应用广泛.C语言的设计目标是提供一种能以简易的方式编译.处理低级存储器.产生少量的机器码以及不需要任何运行环境支持便能运行的'编程语言.今天就为大家 ...

  9. 给自己:得失心莫太重,功利心莫太强

    得失心莫太重 得失性重,意味着情绪会非常影响你的注意力,很多事情你难以专注的投入,对于事情的完成无疑是不好的.而且,你可能不知道自己到底喜欢什么,不喜欢什么,因为外在的评价标准对你的影响太大. 功利心 ...

最新文章

  1. 讲解 Zookeeper 的五个核心知识点
  2. 应用程序的数据库从Sql Server迁移到Oracle
  3. 深入浅出理解c++虚函数
  4. 深度学习训练的小技巧,调参经验。总结与记录。
  5. hdu 6899 Xor 数位dp
  6. 数学图形之Boy surface
  7. 如何删除虚拟机上的操作系统、删除新建的虚拟机
  8. python scikit_Python SciKit学习教程
  9. NLP自然语言理解-中科院(宗成庆) P1~P4
  10. 使用JConsole观察分析Java程序的运行(转)
  11. NMOS管和PMOS管开关控制电路原理及应用
  12. 汇率实时行情查询接口
  13. obs,直播文字画面模糊处理
  14. 数据库大表如何优化?
  15. OceanBase 4.0 all-in-one 版本快速尝鲜安装步骤
  16. 如何用div实现炫酷3D球体?
  17. RGB与YUV格式详解
  18. 常用 Excel 公式列表
  19. 12V输出4.2V1A电池充电芯片
  20. JS中window.showModalDialog()参数及方法

热门文章

  1. 敏捷开发之道 总结小记
  2. 2.递归解决年龄问题
  3. 请帮小明同学设计一个程序,输入上次考试成绩(int)和本次考试成绩(int),然后输出成绩提高百分比,保留2位小数。
  4. 有一天,如果你和计算机一样思考问题,真是太太太太有趣了
  5. 计算机中的微信无法启动,无法打开微信计算机版本文件如果无法打开微信计算机版本怎么办...
  6. 性能优化指标的性能指标,及其如何量化
  7. 漫画|假如一个程序员有“社交牛逼症”
  8. 2020年ui设计师就业前景怎么样?2020ui设计师的缺口大吗
  9. CISCO MFC中部署Firepower FTD高可用(HA)---By 年糕泰迪
  10. Caffe Model Zoo