首页 > 其他分享 >莫队学习笔记

莫队学习笔记

时间:2023-08-24 21:23:44浏览次数:36  
标签:cnt le sum sqrt 学习 笔记 ans 莫队

学习莫队是非常有必要的
众所周知,莫队是一种优越的暴力算法,当我们在 \(NOIP\) 等考试中数据结构不会打且问题是离线时,我们就可以:莫队,启动!
好,切入正题,我们现在来看看莫队是什么:
例题传送门
简要题意:给定一个长度为 \(n\) 的序列 \(a\),然后再给一个数字 \(k\),再给出 \(m\) 组询问,每组询问给出一个区间,求这个区间里面有多少个子区间的异或值为 \(k\)。
\(1 \le n,m \le 10 ^ 5\),\(0 \le k,a_i \le 10^6\),\(1 \le l_i \le r_i \le n\)。

首先,他不是莫队的板子,所以我们先不讲莫队,先讲一些针对这道题的一些 \(trick\)

  • 我们首先考虑定义 \(sum_i=sum_{i-1}\oplus a_i\),容易证明,子区间 \([l,r]\) 的异或值就变成了两个数的异或值: \(sum_r \oplus sum_{l-1}\)

然后,我们开始讲莫队:

  • 首先,我们定义 \(cnt_i\) 表示区间\([l,r]\) 中 \(sum=i\) 的个数

  • 其次,对于区间 \([l,r]\),我们考虑已经知道该区间的答案 \(ans_{l,r}\),以及所有的 \(cnt_i\)

  • 考虑,区间 \([l,r+1]\) 的答案,易证:\(ans_{l,r+1}=ans_{l,r}+cnt_{sum_{r+1}\oplus k}\),然后,\(cnt_{sum{r+1}}++\)

  • 考虑,区间 \([l,r-1]\) 的答案,易证:\(ans_{l,r-1}=ans_{l,r}-cnt_{sum_r\oplus k}\),然后,\(cnt_{sum_r}--\)

  • 考虑,区间 \([l+1,r]\) 的答案,易证:\(ans_{l+1,r}=ans_{l,r}-cnt_{sum_l\oplus k}\),然后,\(cnt_{sum_l}--\)

  • 考虑,区间 \([l-1,r]\) 的答案,易证:\(ans_{l-1,r}=ans_{l,r}+cnt_{sum_{l-1}\oplus k}\),然后,\(cnt_{sum{l-1}}++\)

  • 我们发现,只要我们令 \(le=1,ri=0\),然后让 \(le,ri\) 进行加减到达 \([l,r]\) 就可知道 这个区间 \([l,r]\) 的答案,因为修改是\(O(1)\),但最坏是修改 \(n\) 次,所以是 \(O(n)\)。

  • 有 \(q\) 个询问,所以时间复杂度是 \(O(nq)\)

  • 修改的时间复杂度已经不能再降了,所以我们考虑在修改次数上动手脚,令修改次数尽可能少,这时候我们就要对询问的区间进行排序,这就是为什么莫队是离线

  • 考虑将一个 \(1-n\) 分块,分成 \(\sqrt n\) 个块,分别是 \(1\sim\sqrt n,\sqrt n+1\sim 2\sqrt n,...,(\sqrt n-1)\sqrt n\sim n\)(注意,\(\sqrt n\)不一定整数,所以只要接近就好了,即 \(\sqrt n\) 向下或向上取整)

  • 我们进行排序,以 \(q.l\) 为第一关键字,但注意,并不是直接令 \(q_i.l<q_j.l\),而是判断 \(q_i.l\) 和 \(q_j.l\) 是否在同一个块内,如果不是的话,才令 \(q_i.l<q_j.l\)。

  • 然后以 \(q.r\) 为第二关键字,如果 \(q_i.l\) 和 \(q_j.l\) 在同一个块内,则令 \(q_i.r<q_j.r\)

  • 这样有什么好处呢?我们考虑 \(l\) 的修改次数,对于每一次修改 \(l\) 移动不超过 \(\sqrt n\) 次(当 \(l\) 在不同块时,只有可能从上一个块到下一个块,所以总的移动次数不超过\(2n\),很小,可以忽略),因为询问有 \(q\) 个,所以修改 \(l\) 的时间复杂度是 \(O(q\sqrt n)\)

  • 再考虑 \(r\) 的修改次数,因为在 \(l\) 属于同一个块的时候,\(r\) 是递增的,所以 \(r\) 的修改次数不超过 \(n\),又因为有 \(\sqrt n\) 个块,所以修改 \(r\) 的时间复杂度是 \(O(n \sqrt n)\)

  • 总的时间复杂度就是 \(O((n+q)\sqrt n)\)

  • \(WC\)(一种比赛),从平方级别变成了根号级别,厉不厉害你莫队,这就通过这道题了

上代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll N=1e5+50,M=1e6+50;
ll n,m,k,sq;
ll a[N],b[N];
struct jgt
{
	ll l,r,id;
}q[N];
bool cmp(jgt t1,jgt t2)
{
	return b[t1.l]==b[t2.l] ? t1.r<t2.r : t1.l<t2.l;
}
ll gs[M*2],now;
void add(ll wz)
{
	now+=gs[a[wz]^k];
	gs[a[wz]]++;
}
void del(ll wz)
{
	gs[a[wz]]--;
	now-=gs[a[wz]^k];
}
ll ans[N];
int main()
{
	scanf("%lld %lld %lld",&n,&m,&k);
	for(ll i=1;i<=n;i++)
	{
		scanf("%lld",&a[i]);
		a[i]^=a[i-1];
	}
	sq=sqrt(n);
	for(ll i=0;i<=n;i++)
	b[i]=i/sq+1;
	for(ll i=1;i<=m;i++)
	{
		scanf("%lld %lld",&q[i].l,&q[i].r);
		q[i].l--;
		q[i].id=i;
	}
	sort(q+1,q+m+1,cmp);
	ll le=0,ri=0;
	gs[0]=1;
	for(ll i=1;i<=m;i++)
	{
		while(ri<q[i].r) add(++ri);
		while(ri>q[i].r) del(ri--);
		while(le<q[i].l) del(le++);
		while(le>q[i].l) add(--le);
		ans[q[i].id]=now;
	}
	for(ll i=1;i<=m;i++)
	printf("%lld\n",ans[i]);
	return 0;
}

标签:cnt,le,sum,sqrt,学习,笔记,ans,莫队
From: https://www.cnblogs.com/pengchujie/p/17655177.html

相关文章

  • 深度学习(十三)——损失函数与反向传播
    一、损失函数:LossFunction官网文档:torch.nn—PyTorch2.0documentation1.LossFunction的作用每次训练神经网络的时候都会有一个目标,也会有一个输出。目标和输出之间的误差,就是用\(Loss\)\(Function\)来衡量的。所以,误差\(Loss\)是越小越好的。此外,我们可以根据误......
  • 「学习笔记」浅入模拟退火
    什么是退火?来自百度百科退火是一种金属热处理工艺,指的是将金属缓慢加热到一定温度,保持足够时间,然后以适宜速度冷却。目的是降低硬度,改善切削加工性;降低残余应力,稳定尺寸,减少变形与裂纹倾向;细化晶粒,调整组织,消除组织缺陷。准确的说,退火是一种对材料的热处理工艺,包括金属材料、非......
  • 总结一下强化学习中的面试问题
    1、PPO算法运用了clip函数限制取值范围,为什么还要加上min呢?2、AC架构与PPO之间的区别?3、什么是装饰器?4、lamada函数?5、什么是model-based与model-free?6、python中map函数的用法?7、准确率、精确率、召回率、F1score的意义?8、PPO的上一个策略收集到的经验可以用多少次?......
  • YTEZ校内数学集训笔记
    计数原理例题1:用一个大写的英文字母或一个阿拉伯数字给教室里的一个座位编号,总共能编出多少种不同的号码?或:\(a\wedgeb\)有\(a\)无\(b\)有\(b\)无\(a\)有\(a\)有\(b\)且:\(a\veeb\)有\(a\)有\(b\)非:\(┐a\)无\(a\)答案:英文字母共有26个,阿拉伯数......
  • 「学习笔记」meet in the middle(折半搜索)
    meetinthemiddle,适用于输入数据较小,但也没小到可以直接用暴力搜索通过的情况。主要的思想就是讲整个搜索过程分成两半进行,最后在将这两半的结果进行合并,对于搜索复杂度为\(O(a^b)\)的情况,meetinthemiddle可以将它优化为\(O(a^{\frac{b}{2}})\)。题目P5691[NOI2001]......
  • 一些学习网站和自己写的两个计算周的函数
    toad:https://blog.csdn.net/zzpl139/article/details/127553557风控指标:https://blog.csdn.net/eroswang/article/details/117735703vintage:https://zhuanlan.zhihu.com/p/163206686风控模型:https://falbang.com/?p=350天池:https://tianchi.aliyun.com/competition/entrance/53183......
  • Unity.UI实习笔记
    1.点击Button弹出Panel功能SetActive:在场景中激活或停用对象。需要注意的是,停用父对象,那么场景中活跃的子对象也会停止,但子对象仍在其层次结构中保持活跃状态。例如停用父对象PhysicsDoor,子对象Door变灰,但在层次结构中仍旧保持活跃状态。引用自博客:https://blog.csdn.net/JF_......
  • SQL注入基础学习6
    SQL注入基础学习6三、sqli-labs的page-26、第24关二次注入基础知识二次注入原理:在第一次进行数据库插入数据的时候,仅仅只是使用了addslashes(addslashes()函数返回在预定义字符之前添加反斜杠的字符串。)或者是借助get_magic_quotes_gpc(php7.4版本之后被弃用)对其中的特殊字符......
  • MySQL基础笔记
    MySQLDDL:操作数据库和表DML:对数据进行增删改DQL:对数据进行查询DCL:对数据库进行权限管理数据库增删改查createdatabaseifnotexistsdb1;#如果数据库不存在才创建dropdatabaseifexistsdb1;#如果数据库存在才删除usedb1;#使用数据库selectDATABASE();#......
  • 【学习笔记】Manacher(马拉车)求回文子串
    点击查看目录目录参考资料与图片来源算法思路具体实现例题解题参考资料与图片来源参考博客我觉得这个博客讲的不好,他只讲看规律得到的结论,原因却不说,怪。参考博客2oi-wiki算法思路对于长度可能为奇可能为偶的情况,首先要预处理字符串,在每个字符左右增加一个无关字符#。......