zoukankan      html  css  js  c++  java
  • 线段树的复杂操作

    一,线段树做区间乘法

    首先要明白,乘法操作高于加法操作

    一般的话会开long long ,要去模

    对于一个节点o,我们设区间和为sum[o],加法标记为add[o],乘法标记为mul[o]

    mul标记的初始值是1,add标记初始值是0 
    在修改值的时候,add的维护需要累加,mul的维护需要累乘

    此时当我们进行区间加的时候,一切照旧

    但是当进行区间乘法的时候

    儿子节点的add标记分别先乘上父亲节点的乘标记再加上父亲节点的加标记 
    (因为父亲节点的加标记已经乘上了一些乘标记了,不需要再乘一次)

    儿子节点的乘标记直接乘上父亲节点的乘标记。

     1 void Mul(ll o,ll l,ll r,ll x,ll y,ll k)
     2 {
     3     if(x<=l && y>=r)
     4     {
     5         add[o]=add[o]%mod*k%mod;//相当于加了k个add[o]
     6         sum[o]=sum[o]*k%mod%mod;
     7         mul[o]=mul[o]*k%mod;
     8         return;
     9     }
    10     ll mid=(l+r)>>1;
    11     down(o,l,r,mid);
    12     if(x<=mid) Mul(o<<1,l,mid,x,y,k);
    13     if(y>=mid+1) Mul(o<<1|1,mid+1,r,x,y,k);
    14     sum[o]=(sum[o<<1]+sum[o<<1|1])%mod;
    15 }

    所以标记下放的时候

     1 void down(ll o,ll l,ll r,ll mid)
     2 {
     3     if(add[o]==0 && mul[o]==1) return;
     4     add[o<<1]=(add[o<<1]*mul[o]+add[o])%mod;
     5     mul[o<<1]=mul[o<<1]*mul[o]%mod;
     6     sum[o<<1]=(sum[o<<1]*mul[o]%mod+add[o]*(mid-l+1)%mod)%mod;
     7     
     8     add[o<<1|1]=(add[o<<1|1]*mul[o]+add[o])%mod;
     9     mul[o<<1|1]=mul[o<<1|1]*mul[o]%mod;
    10     sum[o<<1|1]=(sum[o<<1|1]*mul[o]+add[o]*(r-(mid+1)+1))%mod;
    11     
    12     add[o]=0;mul[o]=1;
    13 }
    View Code

    二,区间除法,开方操作

    除法,开方的操作会让各个数字之间越来越相近,最后变成一串一串连续的数字都是一样的,所以对于这一部分的操作我们一定程度上使用暴力,而如果一段都相等就相当于直接进行区间减法的操作
    (对于单个点或者区间内的数完全相同的区间,可以做成区间减法
    因为除法会使数变小,而相同的数减小的量是相同的)
    那么我们来看如何判断区间一段都相等,那我们只需要维护区间的最值,最小值==最大值就完全相等了
    1除法不能打lazy而是更新到底,复杂度可以保证(log级别),因为很快降到0
    然后
    暴力一波

    代码,见相关的题解,我的

  • 相关阅读:
    MashupGoogle Map API与饭否API的整合应用
    request Form request QueryString
    .net宏
    仿Google的一个鼠标拖动效果(转)
    保存图片时出现"800700de错误"的解决方法
    收到了csdn寄来的书
    网站可以如此复制?
    关于聚会
    GIS区域空间搜索一个必要的优化
    videobox,一个错误的名字
  • 原文地址:https://www.cnblogs.com/adelalove/p/11779177.html
Copyright © 2011-2022 走看看