HDU 4578 Transformation

Time limit 8000 ms
Memory limit 65536 kB
OS Windows
Source 2013ACM-ICPC杭州赛区全国邀请赛

感想

线段树加法乘法大合集,有了这些操作,其他的区间平均值、区间方差什么的都不是事儿了。和这题相比,[AHOI2009]维护序列就太简单了,只有乘法加法区间和……

顺便,一开始不说p的大小,直到输入那里才说是想吓死人啊。

解题思路

和维护序列那题一样,依然从标记之间的关系来看,推一推公式,看一个操作对该区间的其他标记、总和、平方和、立方和的影响。

时间不早了,扔两个链接,去睡了敷衍

垃圾CSDN,开始封禁博客园链接了,急了吧,让你之前设计反人类,让你广告恶心人,活该用户变少

源代码

我这代码仿佛在打表

#include<stdio.h>
#include<string.h>
#include<algorithm>

const long long mod=10007;
int T;
int n,m;
struct Node{
    int l,r;
    long long lazyadd,lazymul,lazyset;
    //0,1,-1.设置set标记时,马上清空add、mul。下放时,如果三个都有,说明是在set之后放的
    long long sum[4];
}t[400010];
inline int ls(int x){return x<<1;}
inline int rs(int x){return x<<1|1;}

void build(int x,int l,int r)
{
    memset(&t[x],0,sizeof(t[x]));
    t[x].l=l;
    t[x].r=r;
    t[x].lazymul=1;
    t[x].lazyset=-1;
    if(l==r) return;
    int mid=l+r>>1;
    build(ls(x),l,mid);
    build(rs(x),mid+1,r);
}

inline void pushdown(int x)
{
    if(~t[x].lazyset)
    {
        long long b=t[x].lazyset%mod;
        t[x].lazyset=-1;
        int len=t[ls(x)].r-t[ls(x)].l+1;
        t[ls(x)].sum[1]=len*b%mod;
        t[ls(x)].sum[2]=len*b%mod*b%mod;
        t[ls(x)].sum[3]=len*b%mod*b*b%mod;
        len=(t[rs(x)].r-t[rs(x)].l+1);
        t[rs(x)].sum[1]=len*b%mod;
        t[rs(x)].sum[2]=len*b%mod*b%mod;
        t[rs(x)].sum[3]=len*b%mod*b*b%mod;
        t[ls(x)].lazyset=t[rs(x)].lazyset=b;
        t[ls(x)].lazyadd=t[rs(x)].lazyadd=0;
        t[ls(x)].lazymul=t[rs(x)].lazymul=1;
    }
    if(t[x].lazymul!=1)
    {
        long long b = t[x].lazymul%mod;
        t[x].lazymul = 1;

        t[ls(x)].lazyadd*=b;t[ls(x)].lazyadd%=mod;
        t[ls(x)].lazymul*=b;t[ls(x)].lazymul%=mod;
        t[ls(x)].sum[1]*=b;
        t[ls(x)].sum[2]*=b*b%mod;
        t[ls(x)].sum[3]*=b*b%mod*b;
        t[ls(x)].sum[1]%=mod;
        t[ls(x)].sum[2]%=mod;
        t[ls(x)].sum[3]%=mod;

        t[rs(x)].lazyadd*=b;t[rs(x)].lazyadd%=mod;
        t[rs(x)].lazymul*=b;t[rs(x)].lazymul%=mod;
        t[rs(x)].sum[1]*=b;
        t[rs(x)].sum[2]*=b*b%mod;
        t[rs(x)].sum[3]*=b*b%mod*b;
        t[rs(x)].sum[1]%=mod;
        t[rs(x)].sum[2]%=mod;
        t[rs(x)].sum[3]%=mod;
    }
    if(t[x].lazyadd)
    {
        long long b=t[x].lazyadd;//顺序321
        t[x].lazyadd=0;
        int len=t[ls(x)].r-t[ls(x)].l+1;
        t[ls(x)].sum[3]+=len*b%mod*b*b%mod+t[ls(x)].sum[1]*b%mod*b*3%mod+t[ls(x)].sum[2]*b*3%mod;
        t[ls(x)].sum[2]+=len*b%mod*b%mod+t[ls(x)].sum[1]*b*2%mod;
        t[ls(x)].sum[1]+=len*b%mod;
        t[ls(x)].sum[1]%=mod;
        t[ls(x)].sum[2]%=mod;
        t[ls(x)].sum[3]%=mod;
        t[ls(x)].lazyadd+=b;t[ls(x)].lazyadd%=mod;
        len=t[rs(x)].r-t[rs(x)].l+1;
        t[rs(x)].sum[3]+=len*b%mod*b*b%mod+t[rs(x)].sum[1]*b%mod*b*3%mod+t[rs(x)].sum[2]*b*3%mod;
        t[rs(x)].sum[2]+=len*b%mod*b%mod+t[rs(x)].sum[1]*b*2%mod;
        t[rs(x)].sum[1]+=len*b%mod;
        t[rs(x)].sum[1]%=mod;
        t[rs(x)].sum[2]%=mod;
        t[rs(x)].sum[3]%=mod;
        t[rs(x)].lazyadd+=b;t[rs(x)].lazyadd%=mod;
    }
}

inline void pushup(int x)
{
    t[x].sum[1]=(t[ls(x)].sum[1]+t[rs(x)].sum[1])%mod;
    t[x].sum[2]=(t[ls(x)].sum[2]+t[rs(x)].sum[2])%mod;
    t[x].sum[3]=(t[ls(x)].sum[3]+t[rs(x)].sum[3])%mod;
}

void add(int x,int l,int r,long long k)
{
    if(l<=t[x].l&&t[x].r<=r)
    {
        t[x].lazyadd+=k;
        t[x].lazyadd%=mod;
        int len=t[x].r-t[x].l+1;
        t[x].sum[3]+=3*k*t[x].sum[2]%mod+3*k*k%mod*t[x].sum[1]%mod+len*k%mod*k*k%mod;
        t[x].sum[2]+=2*k*t[x].sum[1]%mod+len*k%mod*k%mod;
        t[x].sum[1]+=len*k%mod;
        t[x].sum[1]%=mod;
        t[x].sum[2]%=mod;
        t[x].sum[3]%=mod;
        return;
    }
    int mid=t[x].l+t[x].r>>1;
    pushdown(x);
    if(l<=mid) add(ls(x),l,r,k);
    if(r>mid) add(rs(x),l,r,k);
    pushup(x);
}

void mult(int x,int l,int r,long long k)
{
    if(l<=t[x].l&&t[x].r<=r)
    {
        t[x].lazymul*=k;
        t[x].lazymul%=mod;
        t[x].lazyadd*=k;//第一次交题的时候这步操作漏了,打乘法标记的时候记得把加法标记也乘一下
        t[x].lazyadd%=mod;
        t[x].sum[3]*=k*k%mod*k%mod;
        t[x].sum[2]*=k*k%mod;
        t[x].sum[1]*=k;
        t[x].sum[1]%=mod;
        t[x].sum[2]%=mod;
        t[x].sum[3]%=mod;
        return;
    }
    int mid=t[x].l+t[x].r>>1;
    pushdown(x);
    if(l<=mid) mult(ls(x),l,r,k);
    if(r>mid) mult(rs(x),l,r,k);
    pushup(x);
}

void change(int x,int l,int r,long long k)
{
    if(l<=t[x].l&&t[x].r<=r)
    {
        int len=t[x].r-t[x].l+1;
        t[x].lazyset=k,t[x].lazyadd=0,t[x].lazymul=1;
        t[x].sum[3]=len*k%mod*k*k%mod;
        t[x].sum[2]=len*k%mod*k%mod;
        t[x].sum[1]=len*k%mod;
        return;
    }
    int mid=t[x].l+t[x].r>>1;
    pushdown(x);
    if(l<=mid) change(ls(x),l,r,k);
    if(r>mid) change(rs(x),l,r,k);
    pushup(x);
}

long long que(int x,int l,int r,long long p)
{
    if(l<=t[x].l&&t[x].r<=r)
    {
        return t[x].sum[p];
    }
    int mid=t[x].l+t[x].r>>1;
    pushdown(x);
    long long ans=0;
    if(l<=mid) ans+=que(ls(x),l,r,p);
    if(r>mid) ans+=que(rs(x),l,r,p);
    return ans%mod;
}

int main()
{
    while((scanf("%d%d",&n,&m),n||m))
    {
        build(1,1,n);
        int opt,a,b;
        long long c;
        while(m--)
        {
            scanf("%d%d%d%I64d",&opt,&a,&b,&c);//这题是Windows系统
            if(opt==1)
                add(1,a,b,c);
            else if(opt==2)
                mult(1,a,b,c);
            else if(opt==3)
                change(1,a,b,c);
            else if(opt==4)
                printf("%I64d\n",que(1,a,b,c));
        }
    }
    return 0;
}

转载于:https://www.cnblogs.com/wawcac-blog/p/11267455.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值