看样子分块题应该做的还不够。

题目描述

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

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

输入输出格式

输入格式:

输入数据的第一行包含一个正整数 \(n\)。

接下来一行包含 \(n\) 个正整数 \(a_0, a_1, ..., a_{n-1}\)。

之后一行包含一个正整数 \(q\),表示询问的个数。

之后 \(q\) 行,每行包含一个询问。格式如题目中所述。

输出格式:

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

输入输出样例

样例输入:

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

输出样例:

6
0
no
2
8
8

数据范围与约定

对于 \(100\%\) 的数据,\(n \leq100000, \ q \leq 10000, \ a_i \leq 10^9 (0 \leq i < n)\),

QUERY x 中的 \(x \leq 10^{18}\),

MODIFY id x 中的 \(0 \leq \mathrm{id} < n, \ 1 \leq x \leq 10^9\)。

题解:

感觉需要推导的东西还是比较多的。但是以后要记着看到奇怪的(?)数据范围时要想到分块。

这个题有一定的特点,就是两个表达式都是前缀形式。对于 \(\gcd​\) 而言,它一定是递减的,而且不同的数值最多只有 \(O(\log a_i)​\) 个,因为每次至少会变为原来的 \(\frac 12​\)。因此产生变化的位置是可以考虑枚举的。

注意到询问是 \(10000​\) 的,不是很大。我们对原区间进行 \(O(\sqrt n)​\) 分块。

因为要找的是最小的,所以应该从前往后枚举。对于 \(\gcd\) 整块不变的那些块,我们只需要找到其中是否存在异或前缀和恰好为 \(x/\gcd\) 的。这一询问可以用 std::map 来解决。

当涉及单点修改时,我们只需要对当前块中的 map 进行修改就可以了。

实际上 map 中存的是当前块中的异或前缀和,由于我们每次查询都是从前往后查,可以积累一定的信息。因此不必也不能维护全局前缀和,不然修改时影响的范围太大。

不过分块的细节挺多的,包括边界一类的。还要注意复杂度,不能把 gcd() 函数当 \(O(1)\) 的操作用啊啊啊啊啊啊…= =

时间复杂度 \(O(n\log a_i+q\sqrt n\log a_i)\)。

Code:

#include<cstdio>
#include<cstring>
#include<map>
#include<cmath>
#define inf 2147438647
using std::map;
int gcd(int x,int y)
{
while(y)
{
int t=y;
y=x%y;
x=t;
}
return x;
}
map<int,int> f[400];
int a[400][400],g[400][400];
int G[400],sum[400];
int main()
{
int n,m,u;
scanf("%d",&n);
int b=sqrt(n),tmp=0;
for(int i=1;i<=n;++i)
{
int x=(i-1)/b,y=(i-1)%b+1;
scanf("%d",&a[x][y]);
tmp^=a[x][y];
g[x][y]=gcd(a[x][y],g[x][y-1]);
G[x]=g[x][y];
if(f[x].find(tmp)==f[x].end())
f[x][tmp]=y;
if(x!=i/b)
{
sum[x]=tmp;
g[x+1][0]=G[x];
tmp=0;
}
}
scanf("%d",&m);
char op[100];
int tot=ceil((double)n/b)-1;
while(m--)
{
scanf("%s",op);
if(op[0]=='M')
{
scanf("%d",&u);
++u;
int x=(u-1)/b,y=(u-1)%b+1;
scanf("%d",&a[x][y]);
f[x].clear();
tmp=0;
g[x][0]=x?G[x-1]:0;
for(int j=1;j<=b;++j)
{
tmp^=a[x][j];
if(f[x].find(tmp)==f[x].end())
f[x][tmp]=j;
g[x][j]=gcd(a[x][j],g[x][j-1]);
G[x]=g[x][j];
}
sum[x]=tmp;
}
else
{
long long k;
scanf("%lld",&k);
int flag=0;
tmp=0;
int gtmp=a[0][1];
for(int i=0;i<=tot;++i)
{
if(!i||G[i]!=G[i-1])//暴力
{
for(int j=1;j<=b;++j)
{
tmp^=a[i][j];
gtmp=g[i][j];
if((long long)tmp*gtmp==k)
{
flag=1;
printf("%d\n",i*b+j-1);
break;
}
}
if(flag)
break;
}
else
{
gtmp=G[i];
if(k%gtmp==0&&k/gtmp<inf&&f[i].find(k/gtmp^tmp)!=f[i].end())
{
printf("%d\n",i*b+f[i][k/gtmp^tmp]-1);
flag=1;
break;
}
tmp^=sum[i];
}
}
if(flag)
continue;
puts("no");
}
}
return 0;
}

洛谷 P4108 / loj 2119 [HEOI2015] 公约数数列 题解【分块】的更多相关文章

  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. 洛谷P1962 斐波那契数列题解

    题目背景 大家都知道,斐波那契数列是满足如下性质的一个数列: • f(1) = 1 • f(2) = 1 • f(n) = f(n-1) + f(n-2) (n ≥ 2 且 n 为整数) 题目描述 请 ...

  4. 洛谷 P4774 / loj 2721 [NOI2018] 屠龙勇士 题解【同余】【exgcd】【CRT】

    推导过程存在漏洞+exCRT板子没打熟于是期望得分÷实际得分=∞? 题目描述 小 D 最近在网上发现了一款小游戏.游戏的规则如下: 游戏的目标是按照编号 \(1\sim n​\) 顺序杀掉 \(n​\ ...

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

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

  6. 洛谷 P3239 / loj 2112 [HNOI2015] 亚瑟王 题解【期望】【DP】

    ???看不懂的期望DP 题目描述 小 K 不慎被 LL 邪教洗脑了,洗脑程度深到他甚至想要从亚瑟王邪教中脱坑. 他决定,在脱坑之前,最后再来打一盘亚瑟王.既然是最后一战,就一定要打得漂亮.众所周知,亚 ...

  7. 洛谷 P4269 / loj 2041 [SHOI2015] 聚变反应炉 题解【贪心】【DP】

    树上游戏..二合一? 题目描述 曾经发明了零件组装机的发明家 SHTSC 又公开了他的新发明:聚变反应炉--一种可以产生大量清洁能量的神秘装置. 众所周知,利用核聚变产生的能量有两个难点:一是控制核聚 ...

  8. 洛谷P1962 斐波那契数列【矩阵运算】

    洛谷P1962 斐波那契数列[矩阵运算] 题目背景 大家都知道,斐波那契数列是满足如下性质的一个数列: • f(1) = 1 • f(2) = 1 • f(n) = f(n-1) + f(n-2) ( ...

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

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

随机推荐

  1. 598. Range Addition II 矩阵的范围叠加

    [抄题]: Given an m * n matrix M initialized with all 0's and several update operations. Operations are ...

  2. JAVA中mark()和reset()用法

    根据JAVA官方文档的描述,mark(int readlimit)方法表示,标记当前位置,并保证在mark以后最多可以读取readlimit字节数据,mark标记仍有效.如果在mark后读取超过rea ...

  3. 构建使用 Azure 网站的云

    Apurva JoshiSunitha Muthukrishna 在设计云解决方案时,设计始终要为故障做好准备.这一点很重要,应牢记. 然而,许多应用程序并非按照这种方式构建. 出现这种情况的主要原因 ...

  4. javascrip总结12:逻辑运算符与等号运算符

    1 逻辑运算符 逻辑运算的结果只有true 或者 false. 1.1 与&&: 两个表达式为true的时候,结果为true. 1.2 或|| 只要有一个表达式为true,结果为tru ...

  5. HDU 6034 Balala Power! (贪心+坑题)

    题意:给定一个 n 个字符串,然后问你怎么给 a-z赋值0-25,使得给定的字符串看成26进制得到的和最大,并且不能出现前导0. 析:一个很恶心的题目,细节有点多,首先是思路,给定个字符一个权值,然后 ...

  6. Java反射学习:深入学习Java反射机制

    一.Java反射的理解(反射是研究框架的基础之一) Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的 ...

  7. 【转】Android系统概览

    这篇文章其实原文叫 <老罗的Android之旅>导读PPT 是罗升阳的博客,我觉得用“Android系统概览”作为标题更贴切些,对于在应用层已经开发了一段时间的人来说,读完之后会有很多体会 ...

  8. 三、SpringBoot-application.properties配置文件和application.yml配置文件

    其实SpringBoot的配置文件有.properties和.yml两种形式,两种配置文件的效果类似,只不过是格式不同而已,孩儿们可以根据下面这几种张截图,通过对比端口号的配置,以及连接SQLServ ...

  9. RadASM的主题更换!

    RadASM的代码编辑器默认背景色位黑色,我很不习惯,决定更换它,按照下面步骤,我把RadASM的代码编辑器默认背景色成功更换成了白色: 1, 2, 3, 4,

  10. Logic Controller(逻辑控制器)

    逻辑控制器主要用来控制采样器的执行顺序,仅对其子节点的逻辑控制器和采样器其作用. 1.Simple Controller(简单控制器) 简单控制器主要用来组织其他逻辑控制器和采样器,提供了一个块的结构 ...