Transformation HDU - 4578(线段树多种操作)

三个数组分别是lazadd lazmul lazc 记录加数,乘数,和设定的数,lazc1 表示一次方之和lazc2 lazc3 以此类推,其中最要注意的就是乘操作和加操作顺序不同答案是不同的,所以假如设定乘法为先,那么下推函数就要把乘法标记下推放在加法前面,而且更新函数里面,如果在更新乘法的时候碰到此处标记有加法标记存在,先把加数乘了,在更新子树,就可以保证既是顺序不一样答案是一样的,就比如a=c+d,当乘f,可变乘af=cf+df,还有下推函数传入长度的时候傻逼了,居然取模了,取完mod导致区间长度错误,无法计算正确答案,找了一个晚上才找到的,还要感谢大佬的博客。

//#if 0
#include <map>
#include <stack>
#include <queue>
#include <vector>
#include <math.h>
#include <string>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
#include <time.h>
#include <set>
#include <list>
#include <iostream>
#define ll long long
#define ull unsigned long long
#define cls(x) memset(x,0,sizeof(x))
#define clslow(x) memset(x,-1,sizeof(x))
#define INF  0x3f3f3f3f
//typedef long long ll;
using namespace std;
const ll mod=1e4+7;
const int maxn=1e5+50;

ll lazc1[maxn<<2],lazc2[maxn<<2],lazc3[maxn<<2],lazadd[maxn<<2],lazc[maxn<<2],lazmul[maxn<<2];

void Push_up(int rt)
{
    lazc1[rt]=(lazc1[rt<<1]%mod+lazc1[rt<<1|1]%mod)%mod;
    lazc2[rt]=(lazc2[rt<<1]%mod+lazc2[rt<<1|1]%mod)%mod;
    lazc3[rt]=(lazc3[rt<<1]%mod+lazc3[rt<<1|1]%mod)%mod;
}

void Push_down(int rt,ll m)
{
//    cout<<"rt="<<rt<<" "<<lazc[rt]<<" "<<lazadd[rt]<<" "<<lazmul[rt]<<endl;
    if(lazc[rt]!=0){
        lazc1[rt<<1]=lazc[rt]*(m-(m>>1))%mod;
        lazc1[rt<<1|1]=lazc[rt]*(m>>1)%mod;
        lazc2[rt<<1]=lazc1[rt<<1]*lazc[rt]%mod;
        lazc2[rt<<1|1]=lazc1[rt<<1|1]*lazc[rt]%mod;
        lazc3[rt<<1]=lazc2[rt<<1]*lazc[rt]%mod;
        lazc3[rt<<1|1]=lazc2[rt<<1|1]*lazc[rt]%mod;

        lazadd[rt<<1]=0;
        lazadd[rt<<1|1]=0;
        lazmul[rt<<1]=1;
        lazmul[rt<<1|1]=1;
        lazc[rt<<1]=lazc[rt]%mod;
        lazc[rt<<1|1]=lazc[rt]%mod;
        lazc[rt]=0;
    }
    if(lazmul[rt]!=1){

        if(lazadd[rt<<1])lazadd[rt<<1]=lazadd[rt<<1]*lazmul[rt]%mod;
        if(lazadd[rt<<1|1])lazadd[rt<<1|1]=lazadd[rt<<1|1]*lazmul[rt]%mod;
//        if(lazc[rt<<1])lazc[rt<<1]=lazc[rt<<1]*lazmul[rt]%mod;
//        if(lazc[rt<<1|1])lazc[rt<<1|1]=lazc[rt<<1|1]*lazmul[rt]%mod;
        lazmul[rt<<1]=lazmul[rt<<1]*lazmul[rt]%mod;
        lazmul[rt<<1|1]=lazmul[rt<<1|1]*lazmul[rt]%mod;
        lazc1[rt<<1]=lazc1[rt<<1]*lazmul[rt]%mod;
        lazc2[rt<<1]=lazc2[rt<<1]*lazmul[rt]%mod*lazmul[rt]%mod;
        lazc3[rt<<1]=lazc3[rt<<1]*lazmul[rt]%mod*lazmul[rt]%mod*lazmul[rt]%mod;

        lazc1[rt<<1|1]=lazc1[rt<<1|1]*lazmul[rt]%mod;
        lazc2[rt<<1|1]=lazc2[rt<<1|1]*lazmul[rt]%mod*lazmul[rt]%mod;
        lazc3[rt<<1|1]=lazc3[rt<<1|1]*lazmul[rt]%mod*lazmul[rt]%mod*lazmul[rt]%mod;

        lazmul[rt]=1;
    }
    if(lazadd[rt]!=0){
        ll cl=lazadd[rt],cr=lazadd[rt];
        ll cl3=cl*cl%mod*cl%mod,cr3=cr*cr%mod*cr%mod;
        ll cl2=cl*cl%mod,cr2=cr*cr%mod;
        ll ml=(m-(m>>1)),mr=(m>>1);
    lazc3[rt<<1]=(lazc3[rt<<1]+3*cl2%mod*lazc1[rt<<1]%mod+3*cl%mod*lazc2[rt<<1]%mod+ml*cl3%mod)%mod;
    lazc3[rt<<1|1]=(lazc3[rt<<1|1]+3*cr2%mod*lazc1[rt<<1|1]%mod+3*cr%mod*lazc2[rt<<1|1]%mod+mr*cr3%mod)%mod;
    lazc2[rt<<1]=(lazc2[rt<<1]+2*cl%mod*lazc1[rt<<1]+ml*cl2%mod)%mod;
    lazc2[rt<<1|1]=(lazc2[rt<<1|1]+2*cr%mod*lazc1[rt<<1|1]+mr*cr2%mod)%mod;
    lazc1[rt<<1]=(lazc1[rt<<1]+ml*cl%mod)%mod;
    lazc1[rt<<1|1]=(lazc1[rt<<1|1]+mr*cr%mod)%mod;

        lazadd[rt<<1]=(lazadd[rt]%mod+lazadd[rt<<1]%mod)%mod;
        lazadd[rt<<1|1]=(lazadd[rt]%mod+lazadd[rt<<1|1]%mod)%mod;
        lazadd[rt]=0;
    }
}

void Update(int L,int R,int l,int r,int rt,ll c,int ml)
{
    if(L<=l && r<=R)
    {
        ll all=(r-l+1)%mod;
        if(ml==1){
            ll c3=c*c%mod*c%mod;
            lazadd[rt]=(lazadd[rt]+c%mod)%mod;
            lazc3[rt]=(lazc3[rt]+3*c%mod*c%mod*lazc1[rt]%mod+3*c%mod*lazc2[rt]%mod+all*c3%mod)%mod;
            lazc2[rt]=(lazc2[rt]+2*c%mod*lazc1[rt]+all*c%mod*c%mod)%mod;
            lazc1[rt]=(lazc1[rt]+c%mod*(r-l+1)%mod)%mod;
        }
        if(ml==2){
            if(lazadd[rt])lazadd[rt]=lazadd[rt]*c%mod;
            lazmul[rt]=lazmul[rt]*c%mod;

            lazc1[rt]=lazc1[rt]*c%mod;
            lazc2[rt]=lazc2[rt]*c%mod*c%mod;
            lazc3[rt]=lazc3[rt]*c%mod*c%mod*c%mod;
        }
        if(ml==3){
            lazc[rt]=c%mod;
            lazadd[rt]=0;
            lazmul[rt]=1;
            lazc1[rt]=c%mod*all%mod;
            lazc2[rt]=c%mod*lazc1[rt]%mod;
            lazc3[rt]=c%mod*lazc2[rt]%mod;
        }
//        cout<<rt<<" "<<l<<" "<<r<<" "<<lazc[rt]<<" "<<lazadd[rt]<<" "<<lazmul[rt]<<endl;
        return;
    }
//    cout<<" update "<<endl;
    Push_down(rt,(r-l+1));
    int mid=(l+r)>>1;
    if(L<=mid)Update(L,R,l,mid,rt<<1,c,ml);
    if(R>mid)Update(L,R,mid+1,r,rt<<1|1,c,ml);
    Push_up(rt);
}

ll Query(int L,int R,int l,int r,int rt,int ml)
{
    if(L<=l && r<=R)
    {
//        cout<<l<<" "<<r<<" "<<lazc[rt]<<" "<<lazadd[rt]<<" "<<lazmul[rt]<<endl;
        if(ml==1)return lazc1[rt];
        if(ml==2)return lazc2[rt];
        if(ml==3)return lazc3[rt];
    }
//    cout<<" query "<<endl;
//    cout<<l<<" "<<r<<endl;
    Push_down(rt,(r-l+1)%mod);
    ll ANS=0;
    int mid=(l+r)>>1;
    if(L<=mid)ANS=(ANS+Query(L,R,l,mid,rt<<1,ml))%mod;
    if(R>mid)ANS=(ANS+Query(L,R,mid+1,r,rt<<1|1,ml))%mod;
    return ANS;
}

void mulclear(int l,int r,int rt)
{
    lazmul[rt]=1;
    if(l==r)
    {
        return;
    }
    int mid=(l+r)>>1;
    mulclear(l,mid,rt<<1);
    mulclear(mid+1,r,rt<<1|1);
}

int main()
{
//    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);
    int n,m;
    while(~scanf("%d%d",&n,&m) && n!=0 && m!=0){
        memset(lazc,0,sizeof lazc);
        memset(lazc1,0,sizeof lazc1);
        memset(lazc2,0,sizeof lazc2);
        memset(lazc3,0,sizeof lazc3);
        memset(lazadd,0,sizeof lazadd);
        mulclear(1,n,1);
        for(int i=0;i<m;i++){
            int ml,u,v,c;
            scanf("%d%d%d%d",&ml,&u,&v,&c);
            if(ml==4){
                cout<<Query(u,v,1,n,1,c)<<endl;
            }
            else{
                Update(u,v,1,n,1,(ll)c,ml);
            }
        }
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值