bzoj 2821 分块】的更多相关文章

分块: 先预处理,将原序列分成长度为len的许多块,计算从第i块到第j块的答案,(可以做到O(n*n/len)). 每次询问时,将询问的区间分成三部分,:左边,中间,右边,中间是尽量大的一个块区间,其答案已经计算得到,左右两边加起来最多有2*len个元素,暴力计算其对答案的影响.O(q*len*f(n)),f(n)是暴力加入一个元素的代价. 这道题f(n)是log(n) 总的复杂度:f(n) = O( n*n/len + q*len*log(n) ), 当len = n*(q*log(n))-1…
大题思路就是分块,将n个数分成sqrt(n)个块,然后 处理出一个w数组,w[i,j]代表第i个块到第j个块的答案 那么对于每组询问l,r如果l,r在同一个块中,直接暴力做就行了 如果不在同一个块中,l,r区间中整块的部分可以直接由w数组得到答案 然后多出来的部分暴力处理下出现次数,然后再预处理一个b数组,代表没 个数出现的位置,且每个数都连续,那么我们可以二分的找出在多余部分出现的 每个数在整区间内出现多少次,然后和多余部分出现的累加,判断奇偶更新答案 看了lyd的题解,写的挺好(其实这个题就…
题意: N个数,M组询问,每次问[l,r]中有多少个数出现正偶数次. 思路: 把N个数分成sqrt(n)块,预处理d[i][j]表示第i块起点到第j块末尾的答案 枚举起点i,并维护一个数组记录每个数到目前为止出现的次数,从偶变奇.从奇变偶时相应增减答案. 把每个数在数列中出现的位置从小到大排序后放入到一个数组Arr中备用. 读入每个询问[l,r].如果l和r在同一个块中暴力即可,否则设l所在块的末尾为l',r所在块的起点为r',[l'+1,r'-1]的答案已经预处理出.扫描l~l', r'~r的…
题目链接:BZOJ - 2821 题目分析 因为强制在线了,所以无法用莫队..可以使用分块来做. 做法是,将 n 个数分成 n/x 个块,每个块大小为 x .先预处理出 f[i][j] ,表示从第 i 个块到第 j 个块的出现次数为偶数的数的个数. 这个复杂度是 n * (n / x) 的. 然后把数与位置存在结构体里,按照数字第一关键字,位置为第二关键字排序.这样是为了方便之后二分查找 [l, r] 中 Num 出现了几次. 对于每次询问,先把答案加上中间包含的整块的答案.然后对于两边至多 2…
Link: BZOJ 2821 传送门 Solution: 一道类似区间众数的经典分块 由于个数为偶数这样的条件不能支持快速合并 因此要先$O(n*sqrt(n))$预处理出$pre[i][j]$表示第$i$块到第$j$块的答案 同时要建立每种颜色的有序序列方便求出一个区间内某种颜色的个数 这样每次查询时就能$O(1)$得出整块答案,$O(size*logn)$算出非整块的数对答案的影响 Code: #include <bits/stdc++.h> using namespace std; #…
分块,分成N^0.5块.O(N^1.5)预处理出sm[i][j]表示前i块中j的出现次数, ans[i][j]表示第i~j块的答案. 然后就可以O(N^0.5)回答询问了.总复杂度O((N+Q)N^0.5) ----------------------------------------------------------------------------------------- #include<cstdio> #include<algorithm> #include<…
Description 有一个长度为n的序列,序列每个元素的范围[1,c],有m个询问x y,表示区间[x,y]中出现正偶数次的数的种类数. Solution 大力分块解决问题. 把序列分块,f[i][j]表示第i块到第j块的答案,并记录块的前缀数的出现次数. f[i][j]直接暴力算,块的前缀数的出现次数也可以直接算,都是nsqrt(n). 遇到询问x y,中间答案的块可以直接统计,然后再暴力统计左右两边零碎的贡献,也是nsqrt(n). Code #include <cstdio> #in…
基本思路和蒲公英一样 还是预处理出每两个块间的答案 询问时暴力跑两边的贡献 #include<cstdio> #include<cstring> #include<iostream> #include<cmath> #include<vector> #include<ctime> #include<algorithm> #define N 100005 using namespace std; int n,m,c,nn,t…
[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=2821 [算法] 如果不强制在线,显然莫队是可以解决此题的,那么,强制在线怎么办呢? 分块 将这个序列分成sqrt(n)段(sqrt表示开方),预处理每段每个数出现的次数与该段“多少数出现了正偶数次”,就可以在线回答询问了 [代码] #include<bits/stdc++.h> using namespace std; ; ; int i,n,m,c,l,r,x,y,len,bl…
多个询问l,r,求所有子区间异或和中最大是多少 强制在线 做法: 分块+可持久化trie 1.对于每块的左端点i,预处理出i到任意一个j,()i,j)间所有子区间异或和中最大为多少,复杂度O(\(n\sqrt n\)) 2.对于询问x,y: ①x,y属于同一块,O(\(\sqrt n log_2 n\))直接扫 ②x,y不属于同一块,找到x右边第一块的左端点,用预处理求出左端点到y,剩下的直接扫,O(\(\sqrt n log_2 n\)) 注意: 1.区间异或和转化为前缀和之后,要表示任意一个…