hdu4578

题意:

给你一个数组,初始值为零,有四种操作:
(1)”1 x y c”,代表 把区间 [x,y] 上的值全部加c。
(2)”2 x y c”,代表 把区间 [x,y] 上的值全部乘以c。
(3)”3 x y c” 代表 把区间 [x,y]上的值全部赋值为c。
(4)”4 x y p” 代表 求区间 [x,y] 上值的p次方和1<=p<=3。

分析:

明显是线段树维护的题。
一看只有1~3次方就知道线段树要开3变量分别维护。
这几种更新操作之间会相互影响,比如对一个区间进行操作3之后,那么操作1和2就失效了。因此在PushDown传递懒标记的时候,传递的顺序也是重要的。
一次方:
sum[0]=sum[0]+(rl+1)c

二次方:
(a+b)2=a2+2ab+b2
sum[1]=sum[1]+2csum[0]+(rl+1)c2
(注:此处的sum[0]是未更新前的sum[0])

三次方:
(a+b)3=a3+3a2b+3ab2+b3 ;
sum[2]=sum[2]+3csum[1]+3c2sum[0]+(rl+1)c3

代码:

#include<cstdio>
#include<cstring>

using namespace std;
const int N=1001000,mod=10007;
int n,m,x,y,z,k;
struct tree{long long l,r,sum[4],jia,cheng,lazy;}g[4*N];
long long plus(long long &x,long long y){x=(x+y)%mod;}
void cheng(int rt,int val)
{
    if (~g[rt].jia) g[rt].jia=g[rt].jia*val%mod;
    if (~g[rt].lazy) g[rt].lazy=g[rt].lazy*val%mod; else
    if (~g[rt].cheng) g[rt].cheng=g[rt].cheng*val%mod; else
        g[rt].cheng=val;
    g[rt].sum[1]=g[rt].sum[1]*val%mod;
    g[rt].sum[2]=g[rt].sum[2]*val%mod*val%mod;
    g[rt].sum[3]=g[rt].sum[3]*val%mod*val%mod*val%mod;  
}

void jia(int rt,int val)
{
    int l=g[rt].l,r=g[rt].r;
    if (~g[rt].lazy) plus(g[rt].lazy,val); else
    if (~g[rt].jia) plus(g[rt].jia,val); else
    g[rt].jia=val;
    plus(g[rt].sum[3],(r-l+1)*val%mod*val%mod*val%mod);
    plus(g[rt].sum[3],3*g[rt].sum[1]*val%mod*val%mod);
    plus(g[rt].sum[3],3*g[rt].sum[2]*val%mod);

    plus(g[rt].sum[2],(r-l+1)*val%mod*val%mod);
    plus(g[rt].sum[2],2*g[rt].sum[1]*val%mod);

    plus(g[rt].sum[1],(r-l+1)*val%mod);
}

void lazy(int rt,int val)
{
    int l=g[rt].l,r=g[rt].r;
    g[rt].lazy=val;
    g[rt].jia=g[rt].cheng=-1;
    g[rt].sum[1]=(r-l+1)*val%mod;
    g[rt].sum[2]=g[rt].sum[1]*val%mod;
    g[rt].sum[3]=g[rt].sum[2]*val%mod;
}

void pushup(int rt)
{   
    g[rt].sum[1]=(g[2*rt].sum[1]+g[2*rt+1].sum[1])%mod;
    g[rt].sum[2]=(g[2*rt].sum[2]+g[2*rt+1].sum[2])%mod;
    g[rt].sum[3]=(g[2*rt].sum[3]+g[2*rt+1].sum[3])%mod;
}

void pushdown(int rt)
{
    if (g[rt].l==g[rt].r) return;
    if (~g[rt].cheng) cheng(2*rt,g[rt].cheng),cheng(2*rt+1,g[rt].cheng),g[rt].cheng=-1;
    if (~g[rt].jia) jia(2*rt,g[rt].jia),jia(2*rt+1,g[rt].jia),g[rt].jia=-1;
    if (~g[rt].lazy) lazy(2*rt,g[rt].lazy),lazy(2*rt+1,g[rt].lazy),g[rt].lazy=-1;
}

void build(int rt,int l,int r)
{
    g[rt].l=l,g[rt].r=r;
    for (int i=1;i<4;i++)
        g[rt].sum[i]=0;
    g[rt].jia=g[rt].cheng=g[rt].lazy=-1;
    if (l==r) return;
    int mid=(l+r)/2;
    build(2*rt,l,mid);
    build(2*rt+1,mid+1,r);
}

void update(int rt,int ll,int rr,int val,int k)
{
    int l=g[rt].l,r=g[rt].r;
    if (ll<=l && r<=rr) 
    {
        if (k==1) jia(rt,val);
        if (k==2) cheng(rt,val);
        if (k==3) lazy(rt,val);
        return;
    }
    pushdown(rt);
    int mid=(l+r)/2;
    if (ll<=mid) update(2*rt,ll,rr,val,k);
    if (rr> mid) update(2*rt+1,ll,rr,val,k);
    pushup(rt);
}

long long query(int rt,int ll,int rr,int val)
{
    int l=g[rt].l,r=g[rt].r;
    if (ll<=l && r<=rr) 
        return g[rt].sum[val];
    pushdown(rt);
    long long mid=(l+r)/2,res=0;
    if (ll<=mid) res=(res+query(2*rt,ll,rr,val))%mod;
    if (rr> mid) res=(res+query(2*rt+1,ll,rr,val))%mod;
    return res;
}

int main()
{
    while (~scanf("%d%d",&n,&m) && n && m)
    {
        build(1,1,n);
        for (int i=1;i<=m;i++)
        {
            scanf("%d%d%d%d",&k,&x,&y,&z);
            if (k==4)
                printf("%d\n",query(1,x,y,z)); else
                update(1,x,y,z,k);
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值