zoukankan      html  css  js  c++  java
  • HDU4578 线段树(区间更新 + 多种操作)和平方,立方

    参考:https://www.cnblogs.com/H-Vking/p/4297973.html

    题意:

    虽然是比较裸的线段树,但是比较麻烦,并且有很多细节需要考虑,对着别人的ac代码debug了一个晚上。纪念一下

     这道题坑在有三种询问:set , add , mul。所以lazy标记要有三个,如果三个标记同时出现的处理方法——当更新set操作时,就把add标记和mul标记全部取消;当更新mul操作时,如果当前节点add标记存在,就把add标记改为:add * mul。这样的话就可以在PushDown()操作中先执行set,然后mul,最后add。

      麻烦在有三种询问:和 , 平方和 , 立方和。对于set和mul操作来说,这三种询问都比较好弄。

      对于add操作,和的话就比较好弄,按照正常方法就可以;

      平方和这样来推:(a + c)2 = a2 + c2 + 2ac  , 即sum2[rt] = sum2[rt] + (r - l + 1) * c * c + 2 * sum1[rt] * c;

      立方和这样推:(a + c)3 = a3 + c3 + 3a(a2 + ac) , 即sum3[rt] = sum3[rt] + (r - l + 1) * c * c * c + 3 * c * (sum2[rt] + sum1[rt] * c);

      几个注意点:add标记取消的时候是置0,mul标记取消的时候是置1;在PushDown()中也也要注意取消标记,如set操作中取消add和mul,mul操作中更新add; 在add操作中要注意sum3 , sum2 , sum1的先后顺序,一定是先sum3 , 然后sum2 , 最后sum1; int容易爆,还是用LL要保险一点; 最后就是运算较多,不要漏掉东西。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <string>
    #include <vector>
    #include <map>
    #include <set>
    #include <queue>
    #include <list>
    #include <iterator>
    
    using namespace std;
    #define lson l , mid , rt << 1
    #define rson mid + 1 , r , rt << 1 | 1
    #define debug(x) cerr << #x << " = " << x << "
    ";
    
    typedef long long ll;
    const int maxn = 1e5+9;
    const int mdd = 10007;
    
    struct node {
        int l,r;    
        ll sum1,sum2,sum3;
        ll lazy1,lazy2,lazy3;
    }st[maxn<<2];
    
    void allmdd(int rt)
    {
        st[rt].sum1 = st[rt].sum1%mdd;
        st[rt].sum2 = st[rt].sum2%mdd;
        st[rt].sum3 = st[rt].sum3%mdd;
    }
    
    void pushup(int rt)
    {
        st[rt].sum1  = (st[rt<<1].sum1 + st[rt<<1|1].sum1)%mdd;
        st[rt].sum2  = (st[rt<<1].sum2 + st[rt<<1|1].sum2)%mdd;
        st[rt].sum3  = (st[rt<<1].sum3 + st[rt<<1|1].sum3)%mdd;
    }
    
    void pushdown(int rt)
    {
        int len  = st[rt].r - st[rt].l + 1;
        int llen = len - (len>>1);
        int rlen = len>>1;
        if(st[rt].lazy3)
        {
            ll c = st[rt].lazy3%mdd;
            st[rt<<1].lazy3 = st[rt<<1|1].lazy3 = st[rt].lazy3;
            st[rt<<1].lazy1 = st[rt<<1|1].lazy1 =  0;
            st[rt<<1].lazy2 = st[rt<<1|1].lazy2 =  1;
    
            st[rt<<1].sum1 = (llen * (c%mdd))%mdd;
            st[rt<<1|1].sum1 = (rlen * c)%mdd;
            
            st[rt<<1].sum2 = (llen * (c * c)%mdd ) %mdd;
            st[rt<<1|1].sum2 = ((rlen * ((c * c)%mdd))%mdd)%mdd;
            
            st[rt<<1].sum3 = (llen * ((c * c)%mdd * (c % mdd))%mdd)%mdd;
            st[rt<<1|1].sum3 = (rlen * ((c * c)%mdd * (c % mdd))%mdd)%mdd;
            st[rt].lazy3 = 0;
        }
    
        if(st[rt].lazy2 != 1 )
        {
            ll c = st[rt].lazy2 % mdd;
            st[rt<<1].lazy2 = (st[rt<<1].lazy2 * c) % mdd;
            st[rt<<1|1].lazy2 = (st[rt<<1|1].lazy2 * c) % mdd;
            if(st[rt<<1].lazy1){
                st[rt<<1].lazy1 = (st[rt<<1].lazy1 * c)%mdd;
            }
            if(st[rt<<1|1].lazy1){
                st[rt<<1|1].lazy1 = (st[rt<<1|1].lazy1 * c)%mdd;
            }
            st[rt<<1].sum1 = (st[rt<<1].sum1 * c)%mdd;
            st[rt<<1|1].sum1 = (st[rt<<1|1].sum1 * c)%mdd;
    
            st[rt<<1].sum2 = ((st[rt<<1].sum2 * c%mdd)*c)%mdd;
            st[rt<<1|1].sum2 = ((st[rt<<1|1].sum2 * c%mdd)*c)%mdd;
            
            st[rt<<1].sum3 = ((((st[rt<<1].sum3 * c)%mdd)*c%mdd)*c)%mdd;
            st[rt<<1|1].sum3 = ((((st[rt<<1|1].sum3 * c)%mdd)*c%mdd)*c)%mdd;
            st[rt].lazy2 = 1;
        }
    
        if(st[rt].lazy1)
        {
            ll c = st[rt].lazy1;
            st[rt<<1].lazy1  = (st[rt<<1].lazy1  + c)%mdd;
            st[rt<<1|1].lazy1  = (st[rt<<1|1].lazy1  +c)%mdd;
            //注意sum3,sum2,sum1 的顺序;
            st[rt<<1].sum3  = st[rt<<1].sum3 + ((c%mdd)*c%mdd)*c%mdd*llen + 3*c*((st[rt<<1].sum2 + st[rt<<1].sum1 * c)%mdd);
            st[rt<<1|1].sum3  = st[rt<<1|1].sum3 + ((c%mdd)*c%mdd)*c%mdd*rlen +3*c*((st[rt<<1|1].sum2 + st[rt<<1|1].sum1 * c)%mdd);
            
            st[rt<<1].sum2 =  st[rt<<1].sum2 + (((llen *c)%mdd) * c)%mdd + 2*(st[rt<<1].sum1)%mdd*c;         
            st[rt<<1|1].sum2 =  st[rt<<1|1].sum2 + (((rlen *c)%mdd) * c)%mdd + 2*(st[rt<<1|1].sum1*c)%mdd;
            
            st[rt<<1].sum1 = st[rt<<1].sum1 + (llen*c)%mdd;
            st[rt<<1|1].sum1 = st[rt<<1|1].sum1 + (rlen*c)%mdd;
            
            allmdd(rt<<1);allmdd(rt<<1|1);
            st[rt].lazy1 = 0;
        }
    }
    
    void build(int l,int r,int rt)
    {
        st[rt].sum1 = st[rt].sum2 = st[rt].sum3 = 0;
        st[rt].lazy1 = st[rt].lazy3 = 0;
        st[rt].lazy2 = 1;
        st[rt].l = l,st[rt].r = r;
        int mid = (l + r) >> 1;
        if(l == r)return;
        build(lson);
        build(rson);
        pushup(rt);
    }
    void update(int l,int r,int rt,int L,int R,int c,int op)
    {        
        if(l >= L&&r <= R)
        {
            if(op==1)
            {
                st[rt].lazy1 += c;
                st[rt].sum3  =  (st[rt].sum3 + ((c*c%mdd)*c)%mdd*(r-l+1)%mdd + (3*c*(st[rt].sum2 + st[rt].sum1*c)%mdd))%mdd; 
                st[rt].sum2 =    (st[rt].sum2 + (c*c)%mdd*(r-l+1)%mdd + (2 * st[rt].sum1 * c)%mdd)%mdd;
                st[rt].sum1 =   (st[rt].sum1 + (r-l+1)*c%mdd)%mdd;                             
            }
            else if(op==2)
            {    
                st[rt].lazy2 = (st[rt].lazy2 * c)%mdd;
                if(st[rt].lazy1)
                    st[rt].lazy1 = (st[rt].lazy1 * c)%mdd;
                st[rt].sum1 = (st[rt].sum1 * c %mdd)%mdd;
                st[rt].sum2 = (st[rt].sum2 * ((c * c) %mdd))%mdd;
                st[rt].sum3 = (st[rt].sum3 * (((c * c)%mdd  * c) % mdd))%mdd;
            }    
            else if(op==3)
            {
                st[rt].lazy3 = c;
                st[rt].lazy1 = 0;
                st[rt].lazy2 = 1;
                st[rt].sum1 = (((r-l+1)*c )% mdd);
                st[rt].sum2 = (((((r-l+1)* c)%mdd )* c %mdd))%mdd;
                st[rt].sum3 = ((r-l+1)* (((c * c)%mdd  * c) % mdd)); 
            }
            return;
        }
    
        int mid = (l+r)>>1;
        pushdown(rt);
        if(L<=mid)update(lson,L,R,c,op);
        if(R>mid)update(rson,L,R,c,op);
        pushup(rt);
    }
    ll query(int l,int r,int rt,int L,int R,int c)
    {
        if(l>=L&&r<=R)
        {
            if(c == 1)return st[rt].sum1%mdd;
            else if(c == 2)return st[rt].sum2%mdd;
            else return st[rt].sum3%mdd;
        }
        int mid = (l+r)>>1;
        ll ans = 0;
        pushdown(rt);
        if(L<=mid)ans = (ans + query(lson,L,R,c))%mdd;
        if(R>mid)ans = (ans + query(rson,L,R,c))%mdd;
        return ans;
    }
    int main(){
        // freopen("input","r",stdin);
         int n,m;
         while(scanf("%d%d", &n, &m)==2&&n+m)
         {
             // debug(n);
             build(1,n,1);
             while(m--)
             {
                 int op;
                 int a,b,c;
                 scanf("%d%d%d%d", & op, & a,& b, & c);
                 if(op==4){
                     printf("%lld
    ", query(1,n,1,a,b,c)%mdd);
                 }
                 else {
                     update(1,n,1,a,b,c,op);
                 }
             }
         }
        return 0;
    }
  • 相关阅读:
    zbb20181207 springboot @ConfigurationProperties使用
    zbb20181206 logback,lombok 默认日志logback配置解析
    Spring Boot (8) 全局异常处理
    Spring Boot (7) JdbcTemplate访问数据库
    Spring Boot (6) Spring Data JPA
    Spring Boot (4) 静态页面和Thymeleaf模板
    Spring Boot (3) 热部署devtools
    Spring Boot (2) Restful风格接口
    Spring Boot (1) 构建第一个Spring Boot工程
    idea使用maven搭建ssm框架实现登陆商品增删改查
  • 原文地址:https://www.cnblogs.com/ckxkexing/p/9017315.html
Copyright © 2011-2022 走看看