【BZOJ4028】[HEOI2015]公约数数列

Description

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

1. MODIFY id x: 将 a_{id} 修改为 x.
2. QUERY x: 求最小的整数 p (0 <= p < n),使得 gcd(a_0, a_1, ..., a_p) * XOR(a_0, a_1, ..., a_p) = x. 其中 XOR(a_0, a_1, ..., a_p) 代表 a_0, a_1, ..., a_p 的异或和,gcd表示最大公约数。

Input

输入数据的第一行包含一个正整数 n.

接下来一行包含 n 个正整数 a_0, a_1, ..., a_{n - 1}.
之后一行包含一个正整数 q,表示询问的个数。
之后 q 行,每行包含一个询问。格式如题目中所述。

Output

对于每个 QUERY 询问,在单独的一行中输出结果。如果不存在这样的 p,输出 no.

Sample Input

10
1353600 5821200 10752000 1670400 3729600 6844320 12544000 117600 59400 640
10
MODIFY 7 20321280
QUERY 162343680
QUERY 1832232960000
MODIFY 0 92160
QUERY 1234567
QUERY 3989856000
QUERY 833018560
MODIFY 3 8600
MODIFY 5 5306112
QUERY 148900352

Sample Output

6
0
no
2
8
8

HINT

对于 100% 的数据,n <= 100000,q <= 10000,a_i <= 10^9 (0 <= i < n),QUERY x 中的 x <= 10^18,MODIFY id x 中的 0 <= id < n,1 <= x <= 10^9.

题解:做过magical GCD那题之后就知道这个套路了。一个序列的本质不同的前缀gcd只有log个(因为从左往右,gcd每次变化时都至少减半)。所以可以暴力维护每个gcd变化的位置。

然后问题变成了问你一个区间中是否存在一个位置x,使得1到x的异或和=val。考虑分块,块内排序。修改时小块暴力,大块打标记;查询时在块内二分查找有没有sum=val^tag的即可。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn=100010;
typedef long long ll;
int n,m,B,gn;
int tag[1000],v[maxn],s[maxn],sp[maxn],g[100],gp[100],bg[1000];
char str[20];
inline ll rd()
{
ll ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-')f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret*f;
}
int gcd(int a,int b)
{
return !b?a:gcd(b,a%b);
}
inline bool eql(ll a,ll b)
{
return (a==b)||((a)&&(b%a==0));
}
bool cmp(const int &a,const int &b)
{
return (s[a]==s[b])?(a<b):(s[a]<s[b]);
}
void getnxt()
{
int a=gp[gn]+1,c=a/B,i,j;
gn++,g[gn]=gcd(g[gn-1],v[a]);
for(j=a;j<c*B+B&&j<n;j++) if(!eql(g[gn],v[j])) {gp[gn]=j-1; return ;}
if(j==n) {gp[gn]=n-1; return ;}
for(i=c+1;i*B<n;i++) if(!eql(g[gn],bg[i])) break;
if(i*B>=n) {gp[gn]=n-1; return ;}
for(j=i*B;j<i*B+B&&j<n;j++) if(!eql(g[gn],v[j])) {gp[gn]=j-1; return ;}
gp[gn]=n-1; return ;
}
bool query(int x,ll val)
{
if(!eql(g[x],val)) return 0;
val=(!g[x])?val:val/g[x];
int a=gp[x-1]+1,b=gp[x],c=a/B,d=b/B,j;
if(c==d)
{
for(j=a;j<=b;j++) if((s[j]^tag[c])==val) {printf("%d\n",j); return 1;}
return 0;
}
for(j=a;j<c*B+B;j++) if((s[j]^tag[c])==val) {printf("%d\n",j); return 1;}
for(j=c+1;j<d;j++)
{
int l=j*B,r=j*B+B,mid;
while(l<r)
{
mid=(l+r)>>1;
if(s[sp[mid]]>=(val^tag[j])) r=mid;
else l=mid+1;
}
if(r<j*B+B&&s[sp[r]]==(val^tag[j])) {printf("%d\n",sp[r]); return 1;}
}
for(j=d*B;j<=b;j++) if((s[j]^tag[d])==val) {printf("%d\n",j); return 1;}
return 0;
}
int main()
{
n=rd(),B=int(sqrt(double(n)));
int i,j,a,c;
ll b,d;
for(i=0;i<n;i++) v[i]=rd();
gp[0]=-1,g[gn=1]=v[0];
for(i=0;i<n;i++)
{
if(i%B==0) tag[i/B+1]=tag[i/B],s[i]=v[i];
else s[i]=s[i-1]^v[i];
tag[i/B+1]^=v[i],bg[i/B]=gcd(v[i],bg[i/B]),sp[i]=i;
if(!eql(g[gn],v[i])) g[gn+1]=gcd(v[i],g[gn]),gp[gn]=i-1,gn++;
}
gp[gn]=n-1;
for(i=0;i<n;i+=B) sort(sp+i,sp+min(i+B,n),cmp);
m=rd();
for(i=1;i<=m;i++)
{
scanf("%s",str);
if(str[0]=='M')
{
a=rd(),b=rd(),c=a/B,d=v[a],v[a]=b,bg[c]=0;
for(j=c*B;j<min(c*B+B,n);j++) s[j]=(j==c*B)?v[j]:s[j-1]^v[j],sp[j]=j,bg[c]=gcd(bg[c],v[j]);
sort(sp+c*B,sp+min(c*B+B,n),cmp);
for(j=c+1;j*B<n;j++) tag[j]^=(b^d);
gn=0;
while(gp[gn]<n-1) getnxt();
}
else
{
b=rd();
for(j=1;j<=gn&&!query(j,b);j++);
if(j==gn+1) printf("no\n");
}
}
return 0;
}

【BZOJ4028】[HEOI2015]公约数数列 分块的更多相关文章

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

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

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

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

  3. BZOJ4028 HEOI2015公约数数列(分块)

    前缀gcd的变化次数是log的,考虑对每一种gcd查询,问题变为查询一段区间是否存在异或前缀和=x/gcd. 无修改的话显然可以可持久化trie,但这玩意实在没法支持修改.于是考虑分块. 对于每一块将 ...

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

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

  5. [BZOJ4028][HAOI2015]公约数数列[分块+分析暴力]

    题意 题目链接 分析 首先明确 \(xor\) 运算和 \(\rm gcd\) 没有联系! 注意到一个数字取 \(\rm gcd\) 且保证每次取 \(\rm gcd\) 值都会变小的话,最多取 \( ...

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

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

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

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

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

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

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

    -by luogu 不会啊.... 然后%了一发题解, 关键是 考虑序列{$a_n$}的前缀gcd序列, 它是单调不升的,且最多只会改变$log_2N$次,因为每变一次至少除2 于是,当我们询问x时: ...

随机推荐

  1. 通过JBoss反序列化(CVE-2017-12149)浅谈Java反序列化漏洞

    前段时间学校学习J2EE,用到了jboss,顺便看了下jboss的反序列化,再浅谈下反序列化漏洞. Java序列化,简而言之就是把java对象转化为字节序列的过程.而反序列话则是再把字节序列恢复为ja ...

  2. 【转】javascript 的类,原型,继承的理解

    原文: https://www.cnblogs.com/codernie/p/9098184.html ------------------------------------------------ ...

  3. ARM指令中的函数调用

    1. 重要寄存器 SP 栈指针,  每一种异常模式都有其自己独立的r13,它通常指向异常模式所专用的堆栈,也就是说五种异常模式.非异常模式(用户模式和系统模式),都有各自独立的堆栈,用不同的堆栈指针来 ...

  4. 利用 getsockname 和 getpeername 来获取某一个链接的本地地址和远端地址

    在两台计算机上建立一个网络连接,需要五个要素:本机地址 本机端口 协议类型 远端端口 远端地址.那么如何从一个建立好的连接上获取这些信息呢.就需要用到 getsockname  和 getpeerna ...

  5. Linux非阻塞IO(二)网络编程中非阻塞IO与IO复用模型结合

    上文描述了最简易的非阻塞IO,采用的是轮询的方式,这节我们使用IO复用模型.   阻塞IO   过去我们使用IO复用与阻塞IO结合的时候,IO复用模型起到的作用是并发监听多个fd. 以简单的回射服务器 ...

  6. win8硬盘安装Ubuntu14.04双系统參考教程

    硬盘安装,无需光盘.U盘.win8为主.Ubuntu14.04为辅.可将Windows或Ubuntu设置为开机默认启动项.在Ubuntu下可查看.操作Windows系统下的文件:适用于安装和14.04 ...

  7. Android_编程规范与经常使用技巧

    一.Android编码规范 1.java代码中不出现中文,最多凝视中能够出现中文 2.局部变量命名.静态成员变量命名 仅仅能包括字母,单词首字母出第一个外.都为大写,其它字母都为小写 3.常量命名 仅 ...

  8. 公网通过代理访问阿里云vpc redis

    前提条件 如果您需要从本地 PC 端访问 Redis 实例进行数据操作,可以通过在 ECS 上配置端口映射或者端口转发实现.但必须符合以下前提条件: 若 Redis 实例属于专有网络(VPC),ECS ...

  9. shell脚本检测网络是否畅通

    shell初始化安装脚本执行时,需从网络上安装一些rpm包,所有需要先检测网络的畅通性, 代码 #检测网络链接&&ftp上传数据 function networkAndFtp() { ...

  10. 全球IT管理最佳实践之DevOps Master 认证

    原文:http://soft.chinabyte.com/30/13940030.shtml 作者:国际最佳实践管理联盟 孙振鹏 关键字: DevOps.DevOps认证.DevOpsDays.Dev ...