zoukankan      html  css  js  c++  java
  • HDU4578 Transformation 线段树

    这个题让我重新学习了加 乘 在区间的操作

    题解:http://blog.csdn.net/guognib/article/details/25324025?utm_source=tuicool&utm_medium=referral

    代码:也是参考上面的写的

    注:确实有优先级,加只影响自己,乘会影响加,重新设定值会清零所有的标记

          所以向下传的时候,乘和加的操作都晚于最后一次设定值,然后乘的操作要先于加

          所以要先传递set 然后是mul 然后是add

    #include <stdio.h>
    #include <string.h>
    #include <string>
    #include <math.h>
    #include <stack>
    #include <vector>
    #include <algorithm>
    using namespace std;
    typedef long long LL;
    const int N=1e5+5;
    const int mod=10007;
    int q[3][N<<2],setval[N<<2],add[N<<2],mul[N<<2];
    void pushup(int rt){
        for(int i=0;i<3;++i)
          q[i][rt]=(q[i][rt<<1]+q[i][rt<<1|1])%mod;  
    }
    void downset(int rt,int c,int len){
        int a[4];a[1]=c;
        for(int i=2;i<=3;++i)
          a[i]=a[i-1]*a[1]%mod;
        for(int i=0;i<3;++i)
         q[i][rt]=a[i+1]*len%mod;
        setval[rt]=c;
        add[rt]=0;
        mul[rt]=1;
    }
    void downadd(int rt,int c,int len){
        int a[4];a[1]=c;
        for(int i=2;i<=3;++i)
           a[i]=a[i-1]*a[1]%mod;
        q[2][rt]=q[2][rt]+a[3]*len%mod+3*a[2]%mod*q[0][rt]%mod+3*a[1]%mod*q[1][rt]%mod;   
        q[1][rt]=q[1][rt]+a[2]*len%mod+2*a[1]%mod*q[0][rt]%mod;
        q[0][rt]=q[0][rt]+a[1]*len%mod;
        for(int i=0;i<3;++i)q[i][rt]%=mod;
        add[rt]=(add[rt]+c)%mod;
    }
    void downmul(int rt,int c,int len){
       int a[4];a[1]=c;
       for(int i=2;i<=3;++i)
        a[i]=a[i-1]*a[1]%mod;
       for(int i=0;i<3;++i)
        q[i][rt]=(q[i][rt]*a[i+1])%mod;
       mul[rt]=(mul[rt]*c)%mod;
       add[rt]=(add[rt]*c)%mod; 
    }
    void down(int rt,int l,int r){
        int m=(l+r)>>1;
        if(setval[rt]!=-1){
            downset(rt<<1,setval[rt],m-l+1);
            downset(rt<<1|1,setval[rt],r-m);
            setval[rt]=-1;
        }
        if(mul[rt]!=1){
            downmul(rt<<1,mul[rt],m-l+1);
            downmul(rt<<1|1,mul[rt],r-m);
            mul[rt]=1;
        }
        if(add[rt]!=0){
            downadd(rt<<1,add[rt],m-l+1);
            downadd(rt<<1|1,add[rt],r-m);
            add[rt]=0;
        }
    }
    int op,c;
    void modify(int rt,int l,int r,int x,int y){
        if(x<=l&&r<=y){
            if(op==1)downadd(rt,c,r-l+1);
            else if(op==2)downmul(rt,c,r-l+1);
            else downset(rt,c,r-l+1);
            return;
        }
        int m=(l+r)>>1;
        down(rt,l,r);
        if(x<=m)modify(rt<<1,l,m,x,y);
        if(y>m)modify(rt<<1|1,m+1,r,x,y);
        pushup(rt);
    }
    int ask(int rt,int l,int r,int x,int y){
        if(x<=l&&r<=y)return q[c-1][rt];
        int ans=0,m=(l+r)>>1;
        down(rt,l,r);
        if(x<=m)ans=(ans+ask(rt<<1,l,m,x,y))%mod;
        if(y>m)ans=(ans+ask(rt<<1|1,m+1,r,x,y))%mod;
        return ans;
    }
    int main(){
        int n,m;
        while(~scanf("%d%d",&n,&m)){
            if(!n&&!m)break;
            for(int i=0;i<=4*n;++i){
                q[0][i]=q[1][i]=q[2][i]=add[i]=0;  
                mul[i]=1;
                setval[i]=-1;
            }
            while(m--){
                int x,y;
                scanf("%d%d%d%d",&op,&x,&y,&c);
                if(op<=3)modify(1,1,n,x,y);
                else printf("%d
    ",ask(1,1,n,x,y));
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    <Yii 学习>写入日志
    微信支付:curl出错,错误码:60
    PHPstorm创建注释模版
    Yii 常用命令
    Linux启动/停止/重启Mysql数据库的方法
    php foreach跳出本次/当前循环与终止循环方法
    介绍Sublime3下两款Markdown插件
    规范
    业务流程时序图
    数据字典
  • 原文地址:https://www.cnblogs.com/shuguangzw/p/5468481.html
Copyright © 2011-2022 走看看