zoukankan      html  css  js  c++  java
  • hdu4578 Transformation【线段树】

    Yuanfang is puzzled with the question below: 
    There are n integers, a 1, a 2, …, a n. The initial values of them are 0. There are four kinds of operations. 
    Operation 1: Add c to each number between a x and a y inclusive. In other words, do transformation a k<---a k+c, k = x,x+1,…,y. 
    Operation 2: Multiply c to each number between a x and a y inclusive. In other words, do transformation a k<---a k×c, k = x,x+1,…,y. 
    Operation 3: Change the numbers between a x and a y to c, inclusive. In other words, do transformation a k<---c, k = x,x+1,…,y. 
    Operation 4: Get the sum of p power among the numbers between a x and a y inclusive. In other words, get the result of a x p+a x+1 p+…+a y p. 
    Yuanfang has no idea of how to do it. So he wants to ask you to help him. 

    Input

    There are no more than 10 test cases. 
    For each case, the first line contains two numbers n and m, meaning that there are n integers and m operations. 1 <= n, m <= 100,000. 
    Each the following m lines contains an operation. Operation 1 to 3 is in this format: "1 x y c" or "2 x y c" or "3 x y c". Operation 4 is in this format: "4 x y p". (1 <= x <= y <= n, 1 <= c <= 10,000, 1 <= p <= 3) 
    The input ends with 0 0. 

    Output

    For each operation 4, output a single integer in one line representing the result. The answer may be quite large. You just need to calculate the remainder of the answer when divided by 10007.

    Sample Input

    5 5
    3 3 5 7
    1 2 4 4
    4 1 5 2
    2 2 5 8
    4 3 5 3
    0 0

    Sample Output

    307
    7489

    超麻烦的线段树 一共四种操作

    加 乘 赋值 幂

    分别用一个数组表示

    关键在于下方pushdown的操作

    赋值的时候就直接下放 保存的幂也直接求

    加和乘的操作一起下放 用平方和立方公式来求sum

    自己写的不知道为什么RE了 查了半天查不出来 而且好复杂懒得查了.....

    下面是题解的代码

    #include<stdio.h>
    #include<iostream>
    #include<stdlib.h>
    #include<string.h>
    #include<algorithm>
    #include<vector>
    using namespace std;
    #define maxn 110000
    #define lmin 1
    #define rmax n
    #define lson l,(l+r)/2,rt<<1
    #define rson (l+r)/2+1,r,rt<<1|1
    #define root lmin,rmax,1
    #define now l,r,rt
    #define int_now int l,int r,int rt
    #define INF 99999999
    #define LL int
    #define mod 10007
    LL add[maxn*4];
    LL mul[maxn*4];
    LL num[maxn*4];
    LL sum[maxn*4][4];
    void push_up(int_now)
    {
        for(int i=1; i<=3; i++)
            sum[rt][i]=(sum[rt<<1][i]+sum[rt<<1|1][i])%mod;
    }
    void push_down(int_now)
    {
        if(l==r)return;
        int ll=(r+l)/2-l+1;
        int rr=r-(r+l)/2;
        if(num[rt] != 0)
        {
            num[rt<<1] = num[rt<<1|1] = num[rt];
            add[rt<<1] = add[rt<<1|1] = 0;
            mul[rt<<1] = mul[rt<<1|1] = 1;
            sum[rt<<1][1] = (ll)*num[rt<<1]%mod;
            sum[rt<<1][2] = (ll)*num[rt<<1]%mod*num[rt<<1]%mod;
            sum[rt<<1][3] = (ll)*num[rt<<1]%mod*num[rt<<1]%mod*num[rt<<1]%mod;
            sum[(rt<<1)|1][1] = (rr)*num[rt<<1|1]%mod;
            sum[(rt<<1)|1][2] = (rr)*num[rt<<1|1]%mod*num[rt<<1|1]%mod;
            sum[(rt<<1)|1][3] = (rr)*num[rt<<1|1]%mod*num[rt<<1|1]%mod*num[rt<<1|1]%mod;
            num[rt] = 0;
        }
        if(add[rt] != 0 || mul[rt] != 1)
        {
            add[rt<<1] = ( mul[rt]*add[rt<<1]%mod + add[rt] )%mod;
            mul[rt<<1] = mul[rt<<1]*mul[rt]%mod;
            int sum1,sum2,sum3;
            sum1 = (sum[rt<<1][1]*mul[rt]%mod + (ll)*add[rt]%mod)%mod;
            sum2 = (mul[rt] * mul[rt] % mod * sum[rt<<1][2] % mod + 2*add[rt]*mul[rt]%mod * sum[rt<<1][1]%mod + (ll)*add[rt]%mod*add[rt]%mod)%mod;
            sum3 = mul[rt] * mul[rt] % mod * mul[rt] % mod * sum[rt<<1][3] % mod;
            sum3 = (sum3 + 3*mul[rt] % mod * mul[rt] % mod * add[rt] % mod * sum[rt<<1][2]) % mod;
            sum3 = (sum3 + 3*mul[rt] % mod * add[rt] % mod * add[rt] % mod * sum[rt<<1][1]) % mod;
            sum3 = (sum3 + (ll)*add[rt]%mod * add[rt] % mod * add[rt] % mod) % mod;
            sum[rt<<1][1] = sum1;
            sum[rt<<1][2] = sum2;
            sum[rt<<1][3] = sum3;
            add[rt<<1|1] = ( mul[rt]*add[rt<<1|1]%mod + add[rt] )%mod;
            mul[rt<<1|1] = mul[rt<<1|1] * mul[rt] % mod;
            sum1 = (sum[(rt<<1)|1][1]*mul[rt]%mod + (rr)*add[rt]%mod)%mod;
            sum2 = (mul[rt] * mul[rt] % mod * sum[(rt<<1)|1][2] % mod + 2*add[rt]*mul[rt]%mod * sum[(rt<<1)|1][1]%mod + (rr)*add[rt]%mod*add[rt]%mod)%mod;
            sum3 = mul[rt] * mul[rt] % mod * mul[rt] % mod * sum[(rt<<1)|1][3] % mod;
            sum3 = (sum3 + 3*mul[rt] % mod * mul[rt] % mod * add[rt] % mod * sum[(rt<<1)|1][2]) % mod;
            sum3 = (sum3 + 3*mul[rt] % mod * add[rt] % mod * add[rt] % mod * sum[(rt<<1)|1][1]) % mod;
            sum3 = (sum3 + (rr)*add[rt]%mod * add[rt] % mod * add[rt] % mod) % mod;
            sum[(rt<<1)|1][1] = sum1;
            sum[(rt<<1)|1][2] = sum2;
            sum[(rt<<1)|1][3] = sum3;
            add[rt] = 0;
            mul[rt] = 1;
     
        }
    }
    void creat(int_now)
    {
        add[rt]=0;
        mul[rt]=1;
        num[rt]=0;
        for(int i=1; i<=3; i++)sum[rt][i]=0;
        if(l!=r)
        {
            creat(lson);
            creat(rson);
        }
    }
    void update(int ll,int rr,int x,int k,int_now)
    {
        if(ll>r||rr<l)return;
        if(ll<=l&&rr>=r)
        {
            x=x%mod;
            if(k==1)
            {
                add[rt]=(add[rt]+x)%mod;
                sum[rt][3]=(sum[rt][3]+3*sum[rt][2]%mod*x%mod+3*sum[rt][1]%mod*x%mod*x%mod+x*x%mod*x%mod*(r-l+1)%mod)%mod;
                sum[rt][2]=(sum[rt][2]+(r-l+1)*x%mod*x%mod+2*x%mod*sum[rt][1]%mod)%mod;
                sum[rt][1]=(sum[rt][1]+x*(r-l+1)%mod)%mod;
            }
            else if(k==2)
            {
                mul[rt]=(mul[rt]*x)%mod;
                add[rt]=(add[rt]*x)%mod;
                for(int i=1; i<=3; i++)
                {
                    int j=i;
                    LL ans=1;
                    while(j--)ans=(ans*x)%mod;
                    sum[rt][i]=(sum[rt][i]*ans)%mod;
                }
            }
            else
            {
                num[rt]=x;
                mul[rt]=1;
                add[rt]=0;
                for(int i=1; i<=3; i++)
                {
                    int j=i;
                    LL ans=1;
                    while(j--)ans=(ans*x)%mod;
                    sum[rt][i]=(ans*(r-l+1)%mod)%mod;
                }
            }
            return;
        }
        push_down(now);
        update(ll,rr,x,k,lson);
        update(ll,rr,x,k,rson);
        push_up(now);
    }
    LL query(int ll,int rr,int p,int_now)
    {
        if(ll>r||rr<l)return 0;
        if(ll<=l&&rr>=r)
        {
            return sum[rt][p];
        }
        push_down(now);
        return (query(ll,rr,p,lson)+query(ll,rr,p,rson))%mod;
    }
    int main()
    {
        int n,m,k,a,b,c;
        while(~scanf("%d%d",&n,&m)&&(n||m))
        {
            creat(root);
            while(m--)
            {
                scanf("%d%d%d%d",&k,&a,&b,&c);
                if(k<=3)
                {
                    update(a,b,c,k,root);
                }
                else
                {
                    printf("%d
    ",query(a,b,c,root));
                }
            }
        }
        return 0;
    }
    

    RE的代码:

    
    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<stack>
    #define inf 1e18
    using namespace std;
    
    const int maxn = 110005;
    const int mod = 10007;
    int m, n;
    long long sum[maxn << 2][4], lazyadd[maxn<<2], lazymul[maxn<<2], lazynum[maxn<<2];
    
    void pushup(int rt)
    {
        for(int i = 1; i <= 3; i++){
            sum[rt][i] = (sum[rt << 1][i] + sum[rt << 1|1][i]) % mod;
        }
    }
    
    void build(int l, int r, int rt)
    {
        lazyadd[rt] = 0;
        lazymul[rt] = 1;
        lazynum[rt] = 0;
        for(int i = 1; i <= 3; i++)
            sum[rt][i] = 0;
        if(l == r) return;
        int m = (l + r) >> 1;
        build(l, m, rt << 1);
        build(m + 1, r, rt << 1 | 1);
    }
    
    void pushdown(int l, int r, int rt)
    {
        if(l == r) return;
        int m = (l + r) / 2;
        int lnum = m - l + 1, rnum = r - m;
        if(lazynum[rt]){//ж╠╫соб╥е
            lazynum[rt << 1] = lazynum[rt<<1|1] = lazynum[rt];
            lazyadd[rt<<1] = lazyadd[rt<<1|1] = 0;
            lazymul[rt<<1] = lazymul[rt<<1|1] = 1;
            sum[rt<<1][1] = lnum * lazynum[rt<<1] % mod;
            sum[rt<<1][2] = lnum * lazynum[rt<<1] % mod * lazynum[rt<<1] % mod;
            sum[rt<<1][3] = lnum * lazynum[rt<<1] % mod * lazynum[rt<<1] % mod * lazynum[rt<<1] % mod;
            sum[rt<<1|1][1] = rnum * lazynum[rt<<1|1] % mod;
            sum[rt<<1|1][2] = rnum * lazynum[rt<<1|1] % mod * lazynum[rt<<1|1] % mod;
            sum[rt<<1|1][3] = rnum * lazynum[rt<<1|1] % mod * lazynum[rt<<1|1] % mod * lazynum[rt<<1|1] % mod;
            lazynum[rt] = 0;
        }
        if(lazyadd[rt] || lazymul[rt] != 1){
            lazyadd[rt<<1] = (lazymul[rt] * lazyadd[rt<<1] % mod + lazyadd[rt])% mod;
            lazymul[rt<<1] = lazymul[rt] * lazymul[rt<<1] % mod;
            int sum1 = (sum[rt<<1][1] * lazymul[rt] % mod + lnum * lazyadd[rt] % mod) % mod;
            int sum2 = (sum[rt<<1][2] * lazymul[rt] % mod * lazymul[rt] % mod + 2 * lazyadd[rt] * lazymul[rt] % mod * sum[rt<<1][1] % mod + lnum * lazyadd[rt] % mod * lazyadd[rt] % mod) % mod;
            int sum3 = (sum[rt<<1][3] * lazymul[rt] % mod * lazymul[rt] % mod * lazymul[rt] % mod + lnum * lazyadd[rt] % mod * lazyadd[rt] % mod * lazyadd[rt] % mod) % mod;
            sum3 = (sum3 + 3 * lazymul[rt] * lazyadd[rt] % mod * lazyadd[rt] % mod * sum[rt<<1][1] % mod) % mod;
            sum3 = (sum3 + 3 * lazymul[rt] * lazymul[rt] % mod * lazyadd[rt] % mod * sum[rt<<1][2] % mod) % mod;
            sum[rt<<1][1] = sum1;
            sum[rt<<1][2] = sum2;
            sum[rt<<1][3] = sum3;
    
            lazyadd[rt<<1|1] = (lazymul[rt] * lazyadd[rt<<1|1] % mod + lazyadd[rt]) % mod;
            lazymul[rt<<1|1] = lazymul[rt] * lazymul[rt<<1|1] % mod;
            sum1 = (sum[rt<<1|1][1] * lazymul[rt] % mod + lnum * lazyadd[rt] % mod) % mod;
            sum2 = (sum[rt<<1|1][2] * lazymul[rt] % mod * lazymul[rt] % mod + 2 * lazyadd[rt] * lazymul[rt] % mod * sum[rt<<1|1][1] % mod + lnum * lazyadd[rt] % mod * lazyadd[rt] % mod) % mod;
            sum3 = (sum[rt<<1|1][3] * lazymul[rt] % mod * lazymul[rt] % mod * lazymul[rt] % mod + lnum * lazyadd[rt] % mod * lazyadd[rt] % mod * lazyadd[rt] % mod) % mod;
            sum3 = (sum3 + 3 * lazymul[rt] * lazyadd[rt] % mod * lazyadd[rt] % mod * sum[rt<<1|1][1] % mod) % mod;
            sum3 = (sum3 + 3 * lazymul[rt] * lazymul[rt] % mod * lazyadd[rt] % mod * sum[rt<<1|1][2] % mod) % mod;
            sum[rt<<1|1][1] = sum1;
            sum[rt<<1|1][2] = sum2;
            sum[rt<<1|1][3] = sum3;
    
            lazyadd[rt] = 0;
            lazymul[rt] = 1;
        }
    }
    
    void update(int L, int R, int x, int k, int l, int r, int rt)
    {
        if(L > r || R < l)return;
        if(L <= l && R >= r){
            x = x % mod;
            if(k == 1){
                lazyadd[rt] = (lazyadd[rt] + x) % mod;
                sum[rt][3] = (sum[rt][3] + 3 * sum[rt][2] % mod * x % mod + 3 * sum[rt][1] % mod * x % mod * x % mod + (r - l + 1) * x % mod * x % mod * x % mod) % mod;
                sum[rt][2] = (sum[rt][2] + 2 * sum[rt][1] % mod * x % mod + (r - l + 1) * x % mod * x % mod) % mod;
                sum[rt][1] = (sum[rt][1] + (r - l + 1) * x % mod) % mod;
            }
            else if(k == 2){
                lazymul[rt] = lazymul[rt] * x % mod;
                lazyadd[rt] = lazyadd[rt] * x % mod;
                for(int i = 1; i <= 3; i++){
                    int j = i;
                    long long ans = 1;
                    while(j--){
                        ans = (ans * x) % mod;
                    }
                    sum[rt][i] = (sum[rt][i] * ans) % mod;
                }
            }
            else{
                lazynum[rt] = x;
                lazymul[rt] = 1;
                lazyadd[rt] = 0;
                for(int i = 1; i <= 3; i++){
                    int j = i;
                    long long ans = 1;
                    while(j--){
                        ans = (ans * x) % mod;
                    }
                    sum[rt][i] = (ans * (r - l + 1) % mod) % mod;
                }
            }
            return;
        }
        pushdown(l, r, rt);
        int m = (l + r) / 2;
        update(L, R, x, k, l, m, rt<<1);
        update(L, R, x, k, m + 1, r, rt<<1|1);
        pushup(rt);
    }
    
    long long query(int L, int R, int p, int l, int r, int rt)
    {
        if(L > r || R < L) return 0;
        if(L <= l && R >= r){
            return sum[rt][p];
        }
        pushdown(l, r, rt);
        int m = (l + r) / 2;
        return (query(L, R, p, l, m, rt<<1) + query(L, R, p, m + 1, r, rt<<1|1)) % mod;
    
    }
    
    int main()
    {
        while(scanf("%d%d", &n, &m) != EOF && (n || m)){
            build(1, n, 1);
            int k, x, y, c;
            for(int i = 0; i < m; i++){
                scanf("%d%d%d%d", &k, &x, &y, &c);
                if(k == 4){
                    printf("%lld
    ", query(x, y, c, 1, n, 1));
                }
                else{
                    update(x, y, c, k, 1, n, 1);
                }
            }
        }
        return 0;
    }
    
  • 相关阅读:
    SSH Config 那些你所知道和不知道的事 (转)
    解决npm ERR! Unexpected end of JSON input while parsing near的方法
    ES查询-term VS match (转)
    ES查询-match VS match_phrase
    安装使用aria2下载百度网盘内容(转)
    基于CSS3鼠标滑过放大突出效果
    基于jQuery的新浪游戏首页幻灯片
    基于animation.css实现动画旋转特效
    基于jQuery左右滑动切换特效
    基于html5顶部导航3D翻转展开特效
  • 原文地址:https://www.cnblogs.com/wyboooo/p/9643392.html
Copyright © 2011-2022 走看看