题目链接
题解
先说说这题的由来及前身
前身
首先有一个很经典的题目:
维护区间加,查询区间\(gcd\)
如果强行用线段树维护的话,区间加之后就没法直接确定当前区间的\(gcd\),不可直接维护
这个时候就用到了
\(gcd\)的一个性质:
\[(a,b) = (a - b,b)\] 三个的
\(gcd\)也是符合的:
\[(a,b,c) = (a,b,c - b) = (a,b - a,c - b)\] 同样可以推广出
\(n\)个的情况
\[gcd\{a_i\} = gcd(a_1,gcd\{a_j - a_{j - 1}\}) \qquad i \in [1,n] \quad j \in [2,n]\] 也就是说,区间差分了之后,我们要求原区间
\(gcd[l,r]\),就相当于求
\(a_l\)和差分后区间
\([l + 1,r]\)的
\(gcd\) 所以我们只需维护差分区间和区间每个位置的值即可
维护区间值用线段树一点问题都没有
在加法下维护差分区间,一个区间加上一个数,仅影响区间端点的值,所以单点修改即可
所以我们开两棵线段树,一棵维护权值,一棵维护差值的\(gcd\),即可\(O(nlog^2n)\)解决这道题
本题
本题多加入了一个区间乘法操作
本来想
\(yy\)分块的,可后来发现线段树依旧可写
并且暴艹分块 思考一下发现,区间乘法后,区间差分值也乘上那个数,对应
\(gcd\)也乘上一个数,可以使用线段树维护
至于端点的差值改变,只需取出端点的值计算出差值后单点加法修改即可
复杂度依旧是
\(O(nlog^2n)\) 部分分
前\(5\%\),咳,,,
对于
\(n,m \le 300\),暴力求即可
对于没有操作
\(2\)的,就是原版题目
对于
\(n,m \le 3 \times 10^4\)的,可以考虑分块
std
#include #include #include #include #include #include