-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的更多相关文章

  1. 【BZOJ4028】[HEOI2015]公约数数列(分块)

    [BZOJ4028][HEOI2015]公约数数列(分块) 题面 BZOJ 洛谷 题解 看一道题目就不会做系列 首先\(gcd\)最多只会有\(log\)种取值,所以我们可以暴力枚举出所有可能的\(g ...

  2. BZOJ 4028: [HEOI2015]公约数数列 【分块 + 前缀GCD】

    任意门:https://www.lydsy.com/JudgeOnline/problem.php?id=4028 4028: [HEOI2015]公约数数列 Time Limit: 10 Sec   ...

  3. BZOJ 4028: [HEOI2015]公约数数列 分块

    4028: [HEOI2015]公约数数列 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=4028 Description 设计一个数据结 ...

  4. 【BZOJ4028】[HEOI2015]公约数数列 分块

    [BZOJ4028][HEOI2015]公约数数列 Description 设计一个数据结构. 给定一个正整数数列 a_0, a_1, ..., a_{n - 1},你需要支持以下两种操作: 1. M ...

  5. 洛谷 P4108 / loj 2119 [HEOI2015] 公约数数列 题解【分块】

    看样子分块题应该做的还不够. 题目描述 设计一个数据结构. 给定一个正整数数列 \(a_0, a_1, \ldots , a_{n-1}\),你需要支持以下两种操作: MODIFY id x: 将 \ ...

  6. bzoj4028: [HEOI2015]公约数数列

    Description 设计一个数据结构. 给定一个正整数数列 a_0, a_1, ..., a_{n - 1},你需要支持以下两种操作: 1. MODIFY id x: 将 a_{id} 修改为 x ...

  7. bzoj 4028 : [HEOI2015]公约数数列

    之前看了好几次都没什么思路,今天下定决心把这题切了. 观察到$0-x$的gcd最多变化log次,因为它每次变化一定至少要去掉一个质因子,所以我们可以枚举gcd. 因为数据范围比较小,所以想到了分块. ...

  8. [HEOI2015]公约数数列

    不错的分块题 gcd和xor其实并没有联系 这里,xor的按位性质没有半点卵用 gcd的性质却很关键: 一个数组,前缀gcd最多logn个不同的 gcd不太多,(暴力的基础) 所有考虑分块. 分块,每 ...

  9. [BZOJ4028][HEOI2015]公约数数列(分块)

    先发掘性质: 1.xor和gcd均满足交换律与结合率. 2.前缀gcd最多只有O(log)个. 但并没有什么数据结构能同时利用这两个性质,结合Q=10000,考虑分块. 对每块记录这几个信息: 1.块 ...

随机推荐

  1. virtualbox硬盘扩容

    https://blog.csdn.net/ouyang_peng/article/details/53261599 1. cmd界面进入virtualbox安装目录:cd C:\Program Fi ...

  2. jvm垃圾回收的过程

    垃圾回收的过程分为两步: 1.判断对象是否死亡 (1)引用计数器法: ①每当有一个对象引用是,计数器加一,当计数器为0是对象死亡 ②缺点:无法解决循环引用的问题,假设A引用B,B引用A,那么这两个对象 ...

  3. Flask 初印象

    Flask 出生于2010年,集中了其他python web框架的长处,定位于微小项目上. 特点 1 内置开发服务器和调试器 2 于Python单元测试功能无缝衔接 Flask框架提供了一个与Pyth ...

  4. 基于alpine用dockerfile创建的ssh镜像

    1.下载alpine镜像 [root@docker43 ~]# docker pull alpine Using default tag: latest Trying to pull reposito ...

  5. (转)CentOS7安装Nginx1.14.2

    原文:https://blog.csdn.net/zhyfyz/article/details/84957381 https://blog.csdn.net/q85795362/article/det ...

  6. 有意思的App

    掘金 javadoop 专业相机也羡慕奖 – Focos 说个睡前故事 so easy 奖 – 洪恩双语绘本 效率蹭蹭上升奖 – Sorted³ 时光隧道走一回奖 – NOMO 相机 设计师也爱用奖 ...

  7. 探讨e.target与e.currentTarget

    target与currentTarget两者既有区别,也有联系,那么我们就来探讨下他们的区别吧,一个通俗易懂的例子解释一下两者的区别: <!DOCTYPE html> <html&g ...

  8. RocketMQ多Master多Slave模式部署

    每个 Master 配置一个 Slave,有多对Master-Slave,HA采用同步双写方式,主备都写成功,向应用返回成功. 优点:数据与服务都无单点,Master宕机情况下,消息无延迟,服务可用性 ...

  9. linux开机自启动设置,自定义开机启动模版,nginx开机自启动服务

    /etc/init.d 目录,我们把shell脚本放在这个目录下来作为启动脚本 都是用来放服务脚本的,当Linux启动时,会寻找这些目录中的服务脚本,并根据脚本的run level确定不同的启动级别. ...

  10. 谈谈Windows Wow64

    欢迎转载,转载请注明出处:http://www.cnblogs.com/lanrenxinxin/p/4977488.html 本文是<深入理解Windows操作系统 (第六版) >关于6 ...