zoukankan      html  css  js  c++  java
  • HDU 4578 Transformation[线段树]

    http://acm.hdu.edu.cn/showproblem.php?pid=4578
    N个数,4种操作。
    1. [l,r]区间的每个数加上c
    2. [l,r]区间的每个数乘上c
    3. [l,r]区间的所有数都设置为c
    4. 询问区间[l,r]的数的p次方和 (1p3)

    之前做线段树一直很不6,今天自己把这几个维护的式子推了一遍,终于找到点感觉了。
    询问的p只有123,分别维护好就行了。操作3等价于乘0再加c。

    (ax+b)c=acx+bc

    (ax1)p+(ax2)p=ap(xp1+xp2)

    (ax1+b)2+(ax2+b)2=(ax1)2+(ax2)2+2b(ax1+ax2)+2b2

    (x1+b)3+(x2+b)3=(x31+x32)+3b(x21+x22)+3b2(x1+x2)+2b3


    #include<iostream>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    
    #define MID int mid = (L+R)>>1;
    #define CHD int lc = node<<1, rc = node<<1|1;
    #define rep(i,f,t) for(int i = f; i <= t; ++i)
    int n,m;
    typedef long long int64;
    
    const int maxn = 100001<<2;
    const int mod = 10007;
    struct sgt{
        int64 sum[maxn][4];
        int64 addv[maxn];
        int64 mulv[maxn];
        void init(){ addv[1] = mulv[1] = 0; }
        int tp,v;
    
        void pushDown(int node){
            CHD;
            if(mulv[node] != 1){
                mulv[lc] = mulv[lc] * mulv[node] % mod;
                mulv[rc] = mulv[rc] * mulv[node] % mod;
                addv[lc] = addv[lc] * mulv[node] % mod;
                addv[rc] = addv[rc] * mulv[node] % mod;
            }
            if(addv[node] != 0){
                addv[lc] = (addv[lc] + addv[node]) % mod;
                addv[rc] = (addv[rc] + addv[node]) % mod;
            }
            mulv[node] = 1;
            addv[node] = 0;
        }
    
        void maintain(int node,int L,int R){
            CHD;
            if(L != R)
                rep(i,1,3) sum[node][i] = (sum[lc][i] + sum[rc][i]) % mod;
    
            if(mulv[node] == 0){
                rep(i,1,3)sum[node][i] = 0;
            }else if(mulv[node] != 1){
                sum[node][1] = sum[node][1]*mulv[node]%mod;
                sum[node][2] = sum[node][2]*mulv[node]*mulv[node]%mod;
                sum[node][3] = sum[node][3]*mulv[node]*mulv[node]*mulv[node]%mod;
            }
            if(addv[node]){
            //这三个顺序不能反
                sum[node][3] = ( sum[node][3] + addv[node]*sum[node][2]*3%mod 
                                + addv[node]*addv[node]*sum[node][1]*3%mod
                                + addv[node]*addv[node]*addv[node]%mod*(R-L+1)%mod) % mod;
                sum[node][2] = ( sum[node][2] + addv[node]*sum[node][1]*2%mod 
                                + addv[node]*addv[node]*(R-L+1)%mod) % mod;
                sum[node][1] = ( sum[node][1] + addv[node]*(R-L+1) ) % mod;
            }
    
            //叶子结点,可以把标记清除
            if(L == R){
                mulv[node] = 1;
                addv[node] = 0;
            }
        }
    
        void update(int from,int to,int val,int node,int L,int R){
            if(from <= L && R <= to){
                if(tp == 1){
                    addv[node] = (addv[node] + val) % mod;
                } else if(tp == 2){
                    addv[node] = (addv[node] * val) % mod;
                    mulv[node] = (mulv[node] * val) % mod;
                } else {
                    addv[node] = val;
                    mulv[node] = 0;
                }
                maintain(node,L,R);
                return;
            }
            pushDown(node);
            MID;CHD;
            if(from <= mid) update(from,to,val,lc,L,mid);
            else maintain(lc,L,mid);
            if(to > mid) update(from,to,val,rc,mid+1,R);
            else maintain(rc,mid+1,R);
            maintain(node,L,R);
        }
        int query(int from,int to,int node,int L,int R){
            maintain(node,L,R);
            if(from <= L && R <= to){
                return sum[node][v];
            }
            int ans = 0;
            pushDown(node);
            MID;CHD;
            if(from <= mid) ans += query(from,to,lc,L,mid);
            else    maintain(lc,L,mid);
            if(to > mid)  ans += query(from,to,rc,mid+1,R);
            else    maintain(rc,mid+1,R);
            return ans%mod;
        }
        void run(){
            while(m--){
                int f,t;
                scanf("%d%d%d%d",&tp,&f,&t,&v);
                if(tp == 4){
                    int ans = query(f,t,1,1,n);
                    printf("%d
    ",ans);
                } else {
                    update(f,t,v,1,1,n);
                }
            }
        }
    }tree;
    int main(){
        while(scanf("%d%d",&n,&m), n||m){
            tree.init();
            tree.run();
        }
        return 0;
    }
    

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    Android框架之Volley与Glide
    美团点餐—listview内部按钮点击事件
    Android之MaterialDesign应用技术2-仿支付宝上滑搜索框缓慢消失
    Android之MaterialDesign应用技术
    Android之Bmob移动后端云服务器
    Java设计模式总汇二---MVC、中介者设计模式
    Java设计模式总汇一 (适配器、单例、静态代理、简单工厂设计模式)
    Android数据绑定技术二,企业级开发
    再次强调完成的定义(DoD)
    在远程 CSM 课程中体验线上工作坊
  • 原文地址:https://www.cnblogs.com/DSChan/p/4861982.html
Copyright © 2011-2022 走看看