莫队算法小结以及模板题
Posted 鲸头鹳
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了莫队算法小结以及模板题相关的知识,希望对你有一定的参考价值。
被splay折磨了一个星期还是抄模板都wa,调试的时候查数据都发现数据太大不能查的蒟蒻杨澜决定学习莫队算法,
但是
万万没想到
莫队也到处都是坑
----------------------------------------------题记
莫队这个东西就是一个非常简♂单的类似动规的东西,也是那种不会就一直不会,一看题解秒懂的题,[虽然我看题解也半天看不懂但是只是第一道题,万事开头难嘛(也许吧)]
莫队算法是一种基于分块的离线算法,主要用来解决一些区间的询问[就是暴力],我们需要做的就是把询问都存下来然后适当的排序,分块,把内容相近的询问放在一起集中处理[利用前面得到的数据来处理询问]以节省时间...说了像没说一样..但是这个东西的原理就是酱..
我们先按照左端点排序,然后分块。
然后在每个块内按右端点排序。
然后顺序处理即可。块内复杂度:
因为块内右端点是递增的,所以右端点至多变化O(n)次,而左端点 不一定,所以是O(l*l)=O(n)次。
块间跳转:撑死了O(n)。
总复杂度:O(n^1.5)。↑大神ppt里的东西复制下来了...果然比我写的清楚一万倍
那么接下来是第一题
模板题...http://www.cnblogs.com/chadinblog/p/5898011.html←lzx大神的程序和题解.第二题这里也有喵
题目 : 给定长度为n的数列以及正整数,有m个询问每次询问给定两个数l,r,求l≤i≤j≤r,且a(i) xor a(i+1) xor a(i+2) xor ... xor a(j)=k的(i,j)的个数。
输入 : 输入数据第一行为n,m,k,意义如题所示。
第二行n个正整数,第i个数表示这个数列a的第i项。
接下来m行,每行两个整数,表示询问操作的l和r。
第二行n个正整数,第i个数表示这个数列a的第i项。
接下来m行,每行两个整数,表示询问操作的l和r。
输出 : 输出数据包含m行,表示每个询问的答案。
样例输入
6 2 3
1 2 1 1 0 3
1 6
3 5
样例输出
7
0
首先我们要回忆一下已经忘光了的位运算中异或的小知识
我们所需要的重要的一条就是,异或就是其自身的逆运算, a^b^a=b , a^a=0 , 0^a=a;
那么我们就可以用数组a[i]来储存前缀(异或)和来处理这个东西了.......
下面说的x到y的异或和的意思就是a(x) xor a(x+1) xor a(x+2) xor ... xor a(y)
↓代码的一部分
1 p=(int)sqrt(m*1.0); 2 for(int i=1;i<=m/p;i++){ 3 memset(cnt,0,sizeof(cnt)); 4 sort(e+(i-1)*p+1,e+i*p+1,mycmp); 5 long long l=0,r=0,ans=0; 6 cnt[0]++; 7 for(int j=(i-1)*p+1;j<=i*p;j++){ 8 while(r<e[j].y) {r++,ans+=cnt[a[r]^k],cnt[a[r]]++;} 9 /*从异或的性质可以知道如果a[r]^k=z,那么z^a[r]=k; 10 cnt[z]指的是o∈(l,r](左开右闭是因为l声明为0...)满足从第1到第o个数的异或和是z的o有多少个...好麻烦... 11 那么为什么是+cnt[z]? 12 因为a[r]是从1到r的异或和,如果a[r]^一个1到o的异或和=k,那么从o到r的异或和就是k*/ 13 while(l<e[j].x-1){cnt[a[l]]--,ans-=cnt[a[l]^k],l++;} 14 while(l>e[j].x-1){l--,ans+=cnt[a[l]^k],cnt[a[l]]++;} 15 e[j].ans=ans; 16 } 17 }
异或真是个磨人的小妖精啊![棒读]
TBC
接下来的1p应该是袜子那道题...
以上是关于莫队算法小结以及模板题的主要内容,如果未能解决你的问题,请参考以下文章
Luogu 1494 - 小Z的袜子 - [莫队算法模板题]
Luogu 1494 - 小Z的袜子 - [莫队算法模板题][分块]