线段树基本操作
支持单点修改区间求gcd##
因为\(gcd\)满足交换律和结合律,所以和维护区间和没什么区别……
支持区间修改区间求gcd##
因为求\(gcd\)有一个辗转相减法,所以有一个\(gcd(a,b)=gcd(b-a,a)\),推广到多个数也成立。具体证明在fsy神仙的博客里有写(转载的gsj学长的……)
所以对于这个序列维护一个差分数组(记为\(sum\)),这样区间加的时候只需把\(d\)加在\(sum_l\)上,再在\(sum_r+1\)上减一个\(d\)(中间的都抵消掉了),这样就把区间加转化成单点加了。查询的时候先查询\(gcd(sum_{l+1},sum_{l+2},...,sum_r)\),然后由于\(sum_l=a_l-a_{l-1}\)所以对于这个要单独处理,但是由于你的修改可能打在了\(sum\)数组上,而又注意到\(sum_1+sum_2+sum_3+...+sum_l=a_l\),所以把\(sum_1,sum_2,sum_3,...,sum_l\)都加起来,\(ans\)就是这两个数求一个\(gcd\)。
具体的证明和细节可以去戳上面那个链接。
支持区间开方,单点加,区间求和##
值域只有1e9,这个范围内的数开个七八次方(或许还没有)就变成1了,所以维护一个区间最大值,如果区间最大值已经变成1了,就不用执行开方操作了,否则暴力开方即可。
Tips: 欧拉函数,取模函数和开方函数也有相同的特点
支持区间开方,区间加,区间求和##
这个用上面的办法会GG啊,数据卡满了要跑几分钟,所以考虑维护一个区间最大最小值,如果区间的极差\(<=1\),那么考虑如果开方之后的极差和开方之前的极差相等,就打上区间减标记,按区间减处理,其余按上面的处理。
权值线段树##
以权值为下标的线段树,当然你需要先把数据离散化
权值线段树求逆序对###
离散化数据之后一个一个插入线段树查询有多少比它大的即可
根据每个位置之前的逆序对个数还原原排列###
(这个好像和线段树没啥关系啊)对于给定序列进行差分,可以得到每个数在原序列中的排名。