洛谷 P5502 - [JSOI2015]最大公约数(区间 gcd 的性质+分治)
学校模拟赛的某道题让我联想到了这道题……
先讲一下我的野鸡做法。
首先考虑分治,对于左右端点都在 \([L,R]\) 中的区间我们将其分成三类:完全包含于 \([L,mid]\) 的区间,完全包含于 \([mid+1,R]\) 的区间,和跨过中间点的区间。前两种我们只需进一步递归 \([L,mid]\) 和 \([mid+1,R]\) 即可求解出答案,比较麻烦的是第三种。我们考虑先扫一遍预处理出 \(F_i=\gcd(a_i,a_{i+1},\cdots,a_{mid})\),以及 \(G_i=\gcd(a_{mid+1},a_{mid+2},\cdots,a_{i})\),那么对于一个满足 \(l\in[L,mid],r\in[mid+1,R]\),其权值 \(W(l,r)=(r-l+1)·\gcd(F_l,G_r)\),直接枚举依然不可做,不过注意到 \(F_i,G_i\) 不同数的种类不超过 \(\log a_i\) 种,因此考虑对 \(F_i,G_i\) 相同的值,我们只保留其最靠左(右)的一个,然后暴力枚举更新答案即可。这个时间复杂度的计算要动点脑筋,乍一看是 \(n\log^3n\) 的(包括我一开始做这道题时也这么认为),但今天才发现它其实是 2log 的,不妨设 \(n\) 为 \(2\) 的整数次幂,\(n\) 不是 \(2\) 的整数次幂的情况与其最近的 \(2\) 的整数次幂效率上显然只是常数的差别。首先求 \(F_i,G_i\) 肯定是 2log 的,区间长度 1log + gcd 1log,比较棘手的是暴力枚举复杂度是什么,若区间长度 \(<\log n\),那么枚举次数的上界肯定是区间长度的平方,\(T_1=\sum\limits_{i=2^k,k\in\mathbb{Z},i\le\log n}\dfrac{n}{i}·i^2=\sum\limits_{i=2^k,k\in\mathbb{Z},i\le\log n}ni\),又 \(i\) 为 \(2\) 的整数次幂,根据等比数列求和公式,后面那东西是 \(\mathcal O(n\log n)\) 的,若区间长度 \(>\log n\),那么对于长度为 \(i\) 的区间,单次枚举复杂度 \(\log^2n\),而这样的区间最多 \(\dfrac{n}{i}\) 个,因此复杂度就是 \(T_2=\log^2n\sum\limits_{i>\log n,i=2^k,k\in\mathbb{Z}}\dfrac{n}{i}\),还是根据等比数列求和公式,后面的 \(\sum\) 里的东西是 \(\mathcal O(\dfrac{n}{\log n})\) 级别的,因此总枚举次数是 \(\mathcal O(n\log n)\) 的,再加上 gcd 的 \(\mathcal O(\log n)\),总复杂度就是 \(\mathcal O(n\log^2n)\)
const int MAXN=1e5;
ll gcd(ll x,ll y){return (!y)?x:gcd(y,x%y);}
int n;ll a[MAXN+5],ans=0,pre[MAXN+5],suf[MAXN+5];
void solve(int l,int r){
if(l==r) return chkmax(ans,a[l]),void();
int mid=l+r>>1;solve(l,mid);solve(mid+1,r);
for(int i=l;i<=r;i++) pre[i]=suf[i]=0;
for(int i=mid;i>=l;i--) suf[i]=gcd(suf[i+1],a[i]);
for(int i=mid+1;i<=r;i++) pre[i]=gcd(pre[i-1],a[i]);
vector<pair<ll,int> > v1,v2;
for(int i=l;i<=mid;i++) if(i==l||(suf[i]^suf[i-1])) v1.pb(mp(suf[i],mid-i+1));
for(int i=mid+1;i<=r;i++) if(i==r||(pre[i]^pre[i+1])) v2.pb(mp(pre[i],i-mid));
for(int i=0;i<v1.size();i++) for(int j=0;j<v2.size();j++) chkmax(ans,gcd(v1[i].fi,v2[j].fi)*(v1[i].se+v2[j].se));
}
int main(){
scanf("%d",&n);for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
solve(1,n);printf("%lld\n",ans);
return 0;
}
事实上有一个非常 simple 的复杂度也是 2log 的做法,我们固定左端点,那么随着右端点的变化,\(\gcd\) 最多变化 \(\log a_i\) 次,那么我们可以二分找出这 \(\log a_i\) 次的断点,然后每次取断点左边的点更新答案即可,求区间 \(\gcd\) 可以 ST 表,复杂度 \(n\log^2n\)。
最后稍微总结一下这道题带给我们的启示:
- 碰到像区间 gcd 这样固定住左端点,随着右端点的增大,区间权值变化量很小(一般 \(\log n\) 级别)的权值函数,可以考虑二分权值变化的位置,这样即可将 \([1,r]\) 拆分成一段段区间,每段区间内所有 \(l\) 都有 \([l,r]\) 权值相同,这样就比较好维护答案(我记得之前某场模拟赛还有这样一个问题:给定长度为 \(n\) 的数列,要你将序列分成 \(k\) 段,求每段 bitwise or 值之和的最大值,当时一点思路都没有,现在知道了这个技巧,学了 wqs 二分,不就得心应手了?)有时还可以利用排序后差分数组的 gcd 与原数组差分数组的 gcd 相同这一性质进行转化,并运用区间 gcd 的性质维护,具体应用就是校内模拟赛那道题,隐私起见就不把题面亮在这里了(
- 碰到求满足条件的区间个数,或者要你求某个区间权值最大值,一般这个权值还与区间长度有关,可以考虑分治求解(虽然这题分治与不分治效率差别并不是太大)
洛谷 P5502 - [JSOI2015]最大公约数(区间 gcd 的性质+分治)的更多相关文章
- 洛谷 P4513 小白逛公园-区间最大子段和-分治+线段树区间合并(单点更新、区间查询)
P4513 小白逛公园 题目背景 小新经常陪小白去公园玩,也就是所谓的遛狗啦… 题目描述 在小新家附近有一条“公园路”,路的一边从南到北依次排着nn个公园,小白早就看花了眼,自己也不清楚该去哪些公园玩 ...
- 【洛谷2257/BZOJ2820】YY的GCD(数论/莫比乌斯函数)
题目: 洛谷2257 预备知识:莫比乌斯定理(懵逼乌斯定理) \(\mu*1=\epsilon\)(证bu明hui略zheng) 其中(我校学长把\(\epsilon(x)\)叫单位函数但是为什么我没 ...
- 洛谷P1880 石子合并(区间DP)(环形DP)
To 洛谷.1880 石子合并 题目描述 在一个园形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分. 试设计出1 ...
- 洛谷 P5469 - [NOI2019] 机器人(区间 dp+拉格朗日插值)
洛谷题面传送门 神仙题,放在 D1T2 可能略难了一点( 首先显然对于 P 型机器人而言,将它放在 \(i\) 之后它会走到左边第一个严格 \(>a_i\) 的位置,对于 Q 型机器人而言,将它 ...
- 洛谷P4168 蒲公英 分块处理区间众数模板
题面. 许久以前我还不怎么去机房的时候,一位大佬好像一直在做这道题,他称这道题目为"大分块". 其实这道题目的思想不只可以用于处理区间众数,还可以处理很多区间数值相关问题. 让我们 ...
- 洛谷P1063 能量项链(区间DP)(环形DP)
To 洛谷.1063 能量项链 题目描述 在Mars星球上,每个Mars人都随身佩带着一串能量项链.在项链上有N颗能量珠.能量珠是一颗有头标记与尾标记的珠子,这些标记对应着某个正整数.并且,对于相邻的 ...
- Bzoj1018/洛谷P4246 [SHOI2008]堵塞的交通(线段树分治+并查集)
题面 Bzoj 洛谷 题解 考虑用并查集维护图的连通性,接着用线段树分治对每个修改进行分治. 具体来说,就是用一个时间轴表示图的状态,用线段树维护,对于一条边,我们判断如果他的存在时间正好在这个区间内 ...
- 【洛谷4219】[BJOI2014]大融合(线段树分治)
题目: 洛谷4219 分析: 很明显,查询的是删掉某条边后两端点所在连通块大小的乘积. 有加边和删边,想到LCT.但是我不会用LCT查连通块大小啊.果断弃了 有加边和删边,还跟连通性有关,于是开始yy ...
- 题解 洛谷 P3396 【哈希冲突】(根号分治)
根号分治 前言 本题是一道讲解根号分治思想的论文题(然鹅我并没有找到论文),正 如论文中所说,根号算法--不仅是分块,根号分治利用的思想和分块像 似却又不同,某一篇洛谷日报中说过,分块算法实质上是一种 ...
随机推荐
- 工厂模式--摆脱你日复一日new对象却依旧单身的苦恼!
前言 每每谈及到Java,就不免会想到一个悲伤的事实:你是否每天都在new对象,却依然坚守在单身岗上屹立不倒.(所谓面向对象编程hhh),这篇来学一下工厂模式,摆脱new对象的苦恼! 知识点 传统工厂 ...
- 395.至少有 K 个重复字符的最长子串
题目 给你一个字符串 s 和一个整数 k ,请你找出 s 中的最长子串, 要求该子串中的每一字符出现次数都不少于k .返回这一子串的长度. 示例 1: 输入:s = "aaabb" ...
- 用例图示例:使用系统边界表示多个项目 / Using System Boundary to model Multiple Projects in Use Case Diagram
什么是用例图? 用例是一种捕获系统功能需求的技术.用例描述了一个独立于实现细节的期望行为.用例的目标是捕获用户设想的所有系统级功能.从用户的角度来看,用例是关于系统应该做什么的.用例捕获系统利益相关者 ...
- csp总结 (差点爆零的总结)
T1,iterator忘了怎么写了,想了很久都想不出来有什么可以替代,只好O(n^2): T2,不会,只会打暴力 T3,自以为是正解,写了很久大概3h,却一直过不了大样例,大样例输出全是0: T4,不 ...
- 单片机stm32的5个时钟源的详细分析
众所周知STM32有5个时钟源HSI.HSE.LSI.LSE.PLL,其实他只有四个,因为从上图中可以看到PLL都是由HSI或HSE提供的. 其中,高速时钟(HSE和HSI)提供给芯片主体的主时钟.低 ...
- 零基础学习STM32之入门学习路线
可以说就目前的市场需求来看,stm32在单片机领域已经拥有了绝对的地位,51什么的已经过时了也只能拿来打基础了,最后依然会转到stm32来,也正是因为这样stm32的学习者越来越多,其中不难发现绝大部 ...
- Python报错ModuleNotFoundError: No module named 'numpy'
转载:https://blog.csdn.net/qq_39779233/article/details/103224712 Python报错ModuleNotFoundError: No modul ...
- OpenWrt编译报错:Package airfly_receiver is missing dependencies for the following libraries
今天在编译一个OpenWrt测试用例的时候出现报错 Package airfly_receiver is missing dependencies for the following librarie ...
- Ubuntu virtualenv 创建 python2 虚拟环境 激活 退出
首先默认安装了virtualenv 创建python2虚拟环境 your-name@node-name:~/virtual_env$ virtualenv -p /usr/bin/python2 py ...
- distinct-subsequences leetcode C++
Given a string S and a string T, count the number of distinct subsequences of T in S. A subsequence ...