luogu P4108 [HEOI2015]公约数数列——solution


-by luogu
不会啊....
然后%了一发题解,
关键是
考虑序列{$a_n$}的前缀gcd序列,
它是单调不升的,且最多只会改变$log_2N$次,因为每变一次至少除2
于是,当我们询问x时:
对每一段满足前缀gcd不变的部分;
可以用map之类的直接查询这个区间中前缀xor值等于$x\over gcd$的最小下标;
但我们还有单点修改,
考虑分块,——随便分个根号块就好
对每块
维护块从左端到右端元素的xor和,
维护块中左端到右端元素的gcd值,
对每个元素
维护从他所在块的左端点到他自己的xor和与gcd值;
这样修改只影响一块之内的所有元素的相关值和这一块的相关值;
对每块开个map
把左端到每个元素的xor值插到对应块的map中去;
当我们查询x时
枚举每块,
如果到这块之前的前缀gcd等于加入这块之后的前缀gcd(设为gcd),则意味着这块之内(从左端到右端)的所有点的前缀gcd都相等,(前缀gcd单调不升)
这样的话,我们设到这块之前的xor为$XOR_{0,L-1}$我们只需在这块的map中查是否有某个$XOR_{l~i}$值满足$gcd*(XOR_{0,L-1}xorXOR_{l,i})=x$即可,其效率为map的效率,$O(log_2\sqrt{N})$乘上块数即为$O(\sqrt{N}log_2\sqrt{N})$
反之,则暴力枚举这块中的每个元素即可,这种情况不超过log次,其总效率为$O(\sqrt{N}log_2{N})$
至于修改,则直接把对这块所维护的信息重新维护即可即可,块大小为$\sqrt{N}$乘上map的效率为$O(\sqrt{N}log_2\sqrt{N})$
于是其总复杂度为$O(q\sqrt{N}log_2N)$
代码:
#include<map>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
map <int ,int >MP[];
int a[];
int b_size,b_num;
int L[];
int b_gcd[],b_xor[];
int a_gcd[],a_xor[];
int n,q;
char s[];
int GCD(int ,int );
void modify();
void query();
int main()
{
int i,j,k;
scanf("%d",&n);
b_size=sqrt(n);
for(i=;i<=n;i++)
scanf("%d",&a[i]);
for(b_num=i=;i<=n;b_num++,i+=b_size){
L[b_num]=i;
a_xor[i]=a_gcd[i]=a[i];
MP[b_num].insert(pair<int ,int >(a_xor[i],i));
for(j=i+;j<i+b_size&&j<=n;j++){
a_xor[j]=a_xor[j-]^a[j];
a_gcd[j]=GCD(a_gcd[j-],a[j]);
MP[b_num].insert(pair<int ,int >(a_xor[j],j));
}
b_xor[b_num]=a_xor[j-],b_gcd[b_num]=a_gcd[j-];
}
scanf("%d",&q);
for(i=;i<=q;i++){
scanf("%s",s);
if(s[]=='M')
modify();
else
query();
}
}
int GCD(int a,int b){
if(!b)return a;
return GCD(b,a%b);
}
void modify(){
int id,x,i,j,k;
scanf("%d%d",&id,&x),id++;
for(i=j=;j<=n;j+=b_size,i++)
if(j+b_size>id)
break;
MP[i].clear();
a[id]=x;
a_xor[(i-)*b_size+]=a_gcd[(i-)*b_size+]=a[(i-)*b_size+];
MP[i].insert(pair<int ,int >(a_xor[(i-)*b_size+],(i-)*b_size+));
for(j=(i-)*b_size+;j<=i*b_size&&j<=n;j++){
a_xor[j]=a_xor[j-]^a[j];
a_gcd[j]=GCD(a_gcd[j-],a[j]);
MP[i].insert(pair<int ,int >(a_xor[j],j));
}
b_xor[i]=a_xor[j-],b_gcd[i]=a_gcd[j-];
}
void query(){
LL x,xx;
map <int ,int >::iterator iter;
int i,j,k,lasxor=,nowgcd=,lasgcd=;
scanf("%lld",&x);
for(i=;i<=b_num;i++){
nowgcd=GCD(b_gcd[i],lasgcd);
if(nowgcd==lasgcd){
if(x%lasgcd){
lasgcd=nowgcd,lasxor^=b_xor[i];
continue;
}
xx=x/lasgcd;
xx^=lasxor;
if(xx>0x7fffffff){
lasgcd=nowgcd,lasxor^=b_xor[i];
continue;
}
k=xx;
if(MP[i].count(k)==){
iter=MP[i].find(k);
printf("%d\n",iter->second-);
return ;
}
}
else{
for(j=(i-)*b_size+;j<=n&&j<=i*b_size;j++)
if(1ll*(lasxor^a_xor[j])*GCD(lasgcd,a_gcd[j])==x){
printf("%d\n",j-);
return ;
}
}
lasgcd=nowgcd,lasxor^=b_xor[i];
}
printf("no\n");
}
分块还差得远呢
luogu P4108 [HEOI2015]公约数数列——solution的更多相关文章
- 【BZOJ4028】[HEOI2015]公约数数列(分块)
[BZOJ4028][HEOI2015]公约数数列(分块) 题面 BZOJ 洛谷 题解 看一道题目就不会做系列 首先\(gcd\)最多只会有\(log\)种取值,所以我们可以暴力枚举出所有可能的\(g ...
- BZOJ 4028: [HEOI2015]公约数数列 【分块 + 前缀GCD】
任意门:https://www.lydsy.com/JudgeOnline/problem.php?id=4028 4028: [HEOI2015]公约数数列 Time Limit: 10 Sec ...
- BZOJ 4028: [HEOI2015]公约数数列 分块
4028: [HEOI2015]公约数数列 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=4028 Description 设计一个数据结 ...
- 【BZOJ4028】[HEOI2015]公约数数列 分块
[BZOJ4028][HEOI2015]公约数数列 Description 设计一个数据结构. 给定一个正整数数列 a_0, a_1, ..., a_{n - 1},你需要支持以下两种操作: 1. M ...
- 洛谷 P4108 / loj 2119 [HEOI2015] 公约数数列 题解【分块】
看样子分块题应该做的还不够. 题目描述 设计一个数据结构. 给定一个正整数数列 \(a_0, a_1, \ldots , a_{n-1}\),你需要支持以下两种操作: MODIFY id x: 将 \ ...
- bzoj4028: [HEOI2015]公约数数列
Description 设计一个数据结构. 给定一个正整数数列 a_0, a_1, ..., a_{n - 1},你需要支持以下两种操作: 1. MODIFY id x: 将 a_{id} 修改为 x ...
- bzoj 4028 : [HEOI2015]公约数数列
之前看了好几次都没什么思路,今天下定决心把这题切了. 观察到$0-x$的gcd最多变化log次,因为它每次变化一定至少要去掉一个质因子,所以我们可以枚举gcd. 因为数据范围比较小,所以想到了分块. ...
- [HEOI2015]公约数数列
不错的分块题 gcd和xor其实并没有联系 这里,xor的按位性质没有半点卵用 gcd的性质却很关键: 一个数组,前缀gcd最多logn个不同的 gcd不太多,(暴力的基础) 所有考虑分块. 分块,每 ...
- [BZOJ4028][HEOI2015]公约数数列(分块)
先发掘性质: 1.xor和gcd均满足交换律与结合率. 2.前缀gcd最多只有O(log)个. 但并没有什么数据结构能同时利用这两个性质,结合Q=10000,考虑分块. 对每块记录这几个信息: 1.块 ...
随机推荐
- java后端导出excel表格
转载 :https://www.cnblogs.com/zhaoyuwei/p/9038135.html 不需要在实体类些@Excel(name = "登录名", width = ...
- python并发编程之进程池,线程池concurrent.futures
进程池与线程池 在刚开始学多进程或多线程时,我们迫不及待地基于多进程或多线程实现并发的套接字通信,然而这种实现方式的致命缺陷是:服务的开启的进程数或线程数都会随着并发的客户端数目地增多而增多, 这会对 ...
- 57.storm拓扑结构调整
几个概念 Topology(拓扑):Spout.Bolt组成的一个完整的流程结构: Stream Grouping:流分组.数据的分发方式: Spout:直译 水龙头,也就是 消息源 的意思: Bol ...
- ASM路径问题导致数据库不能正常启动 -- 报:ORA-03113: end-of-file on communication channel
环境描述: 操作系统版本:Red Hat Enterprise Linux Server release 6.5 (Santiago) 数据库版本:Oracle 11.2.0.4 RAC 场景描述: ...
- (转)shlex — 解析 Shell 风格语法
原文:https://pythoncaff.com/docs/pymotw/shlex-parse-shell-style-syntaxes/171 这是一篇协同翻译的文章,你可以点击『我来翻译』按钮 ...
- Redis学习系列五Set(集合)
一.简介 Redis中的Set(集合)相当于C#中的HashSet,它内部的键值对时无序的.唯一的.用过Dictionary的都知道,Dictionary都知道,里面的每个键值对肯定是唯一的,因为键不 ...
- gridvew使用技巧2
GridVew1_RowDataBindGridView1.DataKeys[e.Row.RowIndex].Values[].ToString(); foreach (GridViewRow t i ...
- [原] ubuntu 13.10 安装 winqq2013
安装及下载地址:http://www.longene.org/forum/viewtopic.php?t=4700 ubuntu 13.10 64位系统安装后无法启动qq,因为缺少程序包.解决方案: ...
- maven install 打包 报错 Cannot run program "gpg.exe": CreateProcess error
打包报错, mvn install后加上参数-Dgpg.skip,例如:mvn install -Dgpg.skip 即可解决. 我们也可以去掉 这个 插件 <plugin> ...
- Tomcat学习总结(15)—— Tomcat优化时的参数分析
(1).maxHttpHeaderSize=”8192” 此选项用于配置:来自于客户端请求的Request和Response的HTTP header 的最大长度,以字节计算.如果不设置,该属性为409 ...