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.块 ...
随机推荐
- MySQL字符集的设置
Notice:文章基于ubuntu系统而写 1.关于MySQL字符集 MySQL的字符集支持(Character Set Support)有两个方面: 字符集(Character set)和排序方式( ...
- 基于iview的后台管理
年前由于时间紧迫,原本使用iview技术开发后台管理系统的大神另有任务,我中途接手该项目,此前对于iview一无所知的我是一脸的懵逼,好在后台管理的整体框架大神已经搭建好了,而我之前对vue也有一定的 ...
- python iter函数用法
iter函数用法简述 Python 3中关于iter(object[, sentinel)]方法有两个参数. 使用iter(object)这种形式比较常见. iter(object, sentinel ...
- Linux学习系列之一:在centos 7.5上安装nginx 以及简单配置
说到Linux我们都知道那是相当相当得重要得啊,在计算机这个行业,开发运维都是离不开它得.我作为一个准毕业生,智商可能不太够,只能自己笨鸟先飞,自己操作起来咯.俗话说的好,好记性不如难笔头嘛.而且ng ...
- WebForm - 文本框回车事件
document.getElementById("Pwd").onkeyup = function (e) { ) { fun_Login(); } };
- js 开发过程中经验及总结记录
一 let 和 var 作用域 1 普通用法 for (var i = 0; i < 5; i++) { console.log(i); } console.log(i); //-- ...
- 封装、构造方法、private、Static与this关键字、main()_Day07
1:成员变量和局部变量的区别(理解) (1)定义位置区别: 成员变量:定义在类中,方法外. 局部变量:定义在方法中,或者方法声明上. (2)初始化值的区别: 成员变量:都有默 ...
- python使用(一)
1.hellopython.py 2.base_option.py 3.str_option.py 4.time_option.py hellopython.py # coding=utf8 __au ...
- Grape教程-params
参数 请求参数可以通过params获取,params是一个hash对象,包括GET.POST.PUT参数,以及路径字符串中的任何命名参数: get :public_timeline do Status ...
- php -- 特殊变量的三种输出
----- 020-3outputs.php ----- <!DOCTYPE html> <html> <head> <meta http-equiv=&qu ...