BZOJ 2821 分块+二分
题意:
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的所有数,统计每个数出现的次数cnt,第一次出现时把它加入队列。
对于队列中的每个数,在数组Arr中二分l’+1和r’-1,得到在[l’+1,r’-1]中出现的次数k。通过对k和当前队列中的数的cnt进行奇偶性讨论更新答案
(from lyd的题解…)
我们就可以vector +lower_bound()
搞定~
(也可以用可持久化线段树之类的东西…)
最后 祝他们幸福……
//By SiriusRen
#include <cmath>
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=100005;
int n,c,m,a[N],Block,block[N],f[1111][1111],vis[N],ans,l,r,stk[N],top;
vector<int>vec[N];
int main(){
scanf("%d%d%d",&n,&c,&m),Block=sqrt(n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]),block[i]=(i-1)/Block+1,vec[a[i]].push_back(i);
for(int i=1;i<=block[n];i++){
memset(vis,0,sizeof(vis));int temp=0;
for(int j=lower_bound(block,block+1+n,i)-block;j<=n;j++){
vis[a[j]]++;
if(vis[a[j]]%2==0)temp++;
else if(vis[a[j]]!=1)temp--;
if(block[j]!=block[j+1])f[i][block[j]]=temp;
}
}
memset(vis,0,sizeof(vis));
for(int i=1;i<=m;i++){
scanf("%d%d",&l,&r);
l=(l+ans)%n+1,r=(r+ans)%n+1;
if(l>r)swap(l,r);ans=0;
int L=block[l]+1,R=block[r];
if(L<R){
int ll=lower_bound(block+1,block+1+n,L)-block-1;
int rr=lower_bound(block+1,block+1+n,R)-block;
R--;top=0;
for(int i=l;i<=ll;i++)vis[a[i]]++,stk[++top]=a[i];
for(int i=rr;i<=r;i++)vis[a[i]]++,stk[++top]=a[i];
ans=f[L][R];
for(int i=1;i<=top;i++)if(vis[stk[i]]){
int t=lower_bound(vec[stk[i]].begin(),vec[stk[i]].end(),rr)-
lower_bound(vec[stk[i]].begin(),vec[stk[i]].end(),ll+1);
if(!t){if(vis[stk[i]]%2==0)ans++;}
else if(t%2==0){if(vis[stk[i]]%2==1)ans--;}
else if(t%2==1&&vis[stk[i]]%2==1)ans++;
vis[stk[i]]=0;
}
}
else{
top=0;
for(int i=l;i<=r;i++)vis[a[i]]++;
for(int i=l;i<=r;i++)if(vis[a[i]]){
if(vis[a[i]]%2==0)ans++;
vis[a[i]]=0;
}
}
printf("%d\n",ans);
}
}
BZOJ 2821 分块+二分的更多相关文章
- bzoj 2821 分块处理
大题思路就是分块,将n个数分成sqrt(n)个块,然后 处理出一个w数组,w[i,j]代表第i个块到第j个块的答案 那么对于每组询问l,r如果l,r在同一个块中,直接暴力做就行了 如果不在同一个块中, ...
- bzoj 2821 分块
分块: 先预处理,将原序列分成长度为len的许多块,计算从第i块到第j块的答案,(可以做到O(n*n/len)). 每次询问时,将询问的区间分成三部分,:左边,中间,右边,中间是尽量大的一个块区间,其 ...
- [BZOJ 2821] 作诗(Poetize) 【分块】
题目链接:BZOJ - 2821 题目分析 因为强制在线了,所以无法用莫队..可以使用分块来做. 做法是,将 n 个数分成 n/x 个块,每个块大小为 x .先预处理出 f[i][j] ,表示从第 i ...
- BZOJ 3343: 教主的魔法(分块+二分查找)
BZOJ 3343: 教主的魔法(分块+二分查找) 3343: 教主的魔法 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1172 Solved: ...
- Bzoj 3343: 教主的魔法(分块+二分答案)
3343: 教主的魔法 Time Limit: 10 Sec Memory Limit: 256 MB Description 教主最近学会了一种神奇的魔法,能够使人长高.于是他准备演示给XMYZ信息 ...
- [BZOJ 2821] 作诗
Link: BZOJ 2821 传送门 Solution: 一道类似区间众数的经典分块 由于个数为偶数这样的条件不能支持快速合并 因此要先$O(n*sqrt(n))$预处理出$pre[i][j]$表示 ...
- BZOJ_3343_教主的魔法_分块+二分查找
BZOJ_3343_教主的魔法_分块+二分查找 题意:教主最近学会了一种神奇的魔法,能够使人长高.于是他准备演示给XMYZ信息组每个英雄看.于是N个英雄们又一次聚集在了一起,这次他们排成了一列被编号为 ...
- 【bzoj2957】楼房重建 分块+二分查找
题目描述 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子.为了简化问题,我们考虑这些事件发生在一个二 ...
- 【bzoj2453】维护队列/【bzoj2120】数颜色 分块+二分
题目描述 你小时候玩过弹珠吗? 小朋友A有一些弹珠,A喜欢把它们排成队列,从左到右编号为1到N.为了整个队列鲜艳美观,小朋友想知道某一段连续弹珠中,不同颜色的弹珠有多少.当然,A有时候会依据个人喜好, ...
随机推荐
- [ Tools ] [ MobaXterm ] [ SSH ] [ Linux ] 中文顯示解決
預設是無法顯示中文的,需要修改連線的 Terminal Setting
- go结构,结构嵌套,接口,指针的测试和结论
package main import ( "fmt" ) //T是M1接受者,不是实现M2接受者 //*T是M1接受者,也是M2的接受者 //所以T对象不可以赋值给接口对象.*T ...
- map参数值取代
public static String processTemplate(String tpl, Map<String, ?> params){ Iterator<String> ...
- Java代码运用及算法思路养成——用*号输出形状
简单的了解了一些循环算法后,尝试用循环算法,输出形状图形 例1矩形与平行四边形的比较(可以看做矩形的每一行在输出前都输出了矩形长度数量-1的空格数量并且依次递减) 例2三角形(三角形可看做半个矩形,考 ...
- 优动漫PAINT发展历程和主要功能
优动漫PAINT也就是我们常说的clip studio paint(CSP)的中文版本,它是一款功能强大的动漫绘图软件.经过五年的成长,优动漫PAINT经历了从青涩到成熟的发展过程,随着软件更多功能的 ...
- Javaee 方法的格式和注意事项
1.构造方法的格式是什么?有哪些注意事项? 修饰符+方法名称+(参数列表),构造的方法没有返回值,方法名称要和类名一样,有属性参数的需要在成员变量前加this,参数列表的值要和指定的方法格式相同. ...
- jquery-ui实现拖拽功能
https://www.runoob.com/jqueryui/jqueryui-tutorial.html
- CSS - 内联元素span 强制换行失败的可能原因
在CSS中,标签span 强制换行失败:(使用display:block) 可能原因:float:left or float:right
- javascript事件列表解说
javascript事件列表解说 事件 浏览器支持 解说 一般事件 onclick IE3.N2 鼠标点击时触发此事件 ondblclick IE4.N4 鼠标双击时触发此事件 onmousedown ...
- LINUX 中 VSFTPD安裝
VSFTPD 简写:vsftpd是very secure FTP daemon 的缩写,是一个完全免费的,开源代码的ftp服务器软件 特点:vsftpd是一款在LINUX发行版中最受推崇的FTP服务器 ...