hdu4578 (多标记线段树)

题意

对于一个区间有4个操作:
1.将a~b都加上c
2.将a~b都乘上c
3.将a~b都变成c
4.查询a~b的每个数的p次方的和。(p=1,2,3)

思路

平方和这样来推:\((a+c)^2=a^2+2ac+c^2\)
\(sum2[rt] = sum2[rt] +2*sum1[rt] * c+(r-l+1)*c*c\)
立方和这样推:\((a+c)^3=a^3+3a^2c+3ac^2+c^3\)
\(sum3[rt]=sum3[rt]+3*sum2[rt]*c+3*sum1[rt]*c*c+(r-l+1)*c*c*c\)
注意懒惰数组下传的先后顺序

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxx = 1e5+10;
const int mod = 10007;
int t[maxx<<2][4],lazy[maxx<<2][4];
void build(int l,int r,int rt)
{
    lazy[rt][1]=1,lazy[rt][2]=0,lazy[rt][3]=0;
    for(int i=1;i<=3;i++)t[rt][i]=0;
    if(l==r)return;
    int mid=(l+r)/2;
    build(l,mid,rt*2);
    build(mid+1,r,rt*2+1);
}
void pushdown(int l,int r,int rt)
{
    if(lazy[rt][3])
    {
        LL c=lazy[rt][3];
        t[rt*2][1]=c*l%mod;
        t[rt*2+1][1]=c*r%mod;
        t[rt*2][2]=c*c%mod*l%mod;
        t[rt*2+1][2]=c*c%mod*r%mod;
        t[rt*2][3]=c*c%mod*c%mod*l%mod;
        t[rt*2+1][3]=c*c%mod*c%mod*r%mod;
        lazy[rt*2][1]=lazy[rt*2+1][1]=1;
        lazy[rt*2][2]=lazy[rt*2+1][2]=0;
        lazy[rt*2][3]=lazy[rt*2+1][3]=c;
        lazy[rt][3]=0;
    }
    if(lazy[rt][1]!=1)
    {
        LL c=lazy[rt][1];
        t[rt*2][3]=t[rt*2][3]*c%mod*c%mod*c%mod;
        t[rt*2+1][3]=t[rt*2+1][3]*c%mod*c%mod*c%mod;
        t[rt*2][2]=t[rt*2][2]*c%mod*c%mod;
        t[rt*2+1][2]=t[rt*2+1][2]*c%mod*c%mod;
        t[rt*2][1]=t[rt*2][1]*c%mod;
        t[rt*2+1][1]=t[rt*2+1][1]*c%mod;
        lazy[rt*2][1]=lazy[rt*2][1]*c%mod;
        lazy[rt*2+1][1]=lazy[rt*2+1][1]*c%mod;
        lazy[rt*2][2]=lazy[rt*2][2]*c%mod;
        lazy[rt*2+1][2]=lazy[rt*2+1][2]*c%mod;
        lazy[rt][1]=1;
    }
    if(lazy[rt][2])
    {
        LL c=lazy[rt][2];
        t[rt*2][3]=(t[rt*2][3]+3*t[rt*2][2]*c%mod+3*t[rt*2][1]*c%mod*c%mod+c*c%mod*c%mod*l%mod)%mod;
        t[rt*2+1][3]=(t[rt*2+1][3]+3*t[rt*2+1][2]*c%mod+3*t[rt*2+1][1]*c%mod*c%mod+c*c%mod*c%mod*r%mod)%mod;
        t[rt*2][2]=(t[rt*2][2]+2*t[rt*2][1]*c%mod+c*c%mod*l%mod)%mod;
        t[rt*2+1][2]=(t[rt*2+1][2]+2*t[rt*2+1][1]*c%mod+c*c%mod*r%mod)%mod;
        t[rt*2][1]=(t[rt*2][1]+c*l%mod)%mod;
        t[rt*2+1][1]=(t[rt*2+1][1]+c*r%mod)%mod;
        lazy[rt*2][2]=(lazy[rt*2][2]+c)%mod;
        lazy[rt*2+1][2]=(lazy[rt*2+1][2]+c)%mod;
        lazy[rt][2]=0;
    }
}
void update(int l,int r,int p,int q,LL c,int op,int rt)
{
    if(p<=l&&r<=q)
    {
        if(op==3)
        {
            t[rt][1]=c*(r-l+1)%mod;
            t[rt][2]=c*c%mod*(r-l+1)%mod;
            t[rt][3]=c*c%mod*c%mod*(r-l+1)%mod;
            lazy[rt][1]=1,lazy[rt][2]=0;lazy[rt][3]=c;
        }
        else if(op==1)
        {
            t[rt][3]=(t[rt][3]+3*t[rt][2]*c%mod+3*t[rt][1]*c%mod*c%mod+c*c%mod*c%mod*(r-l+1)%mod)%mod;
            t[rt][2]=(t[rt][2]+2*t[rt][1]*c%mod+c*c%mod*(r-l+1)%mod)%mod;
            t[rt][1]=(t[rt][1]+c*(r-l+1)%mod)%mod;
            lazy[rt][2]=(lazy[rt][2]+c)%mod;
        }
        else
        {
            t[rt][1]=t[rt][1]*c%mod;
            t[rt][2]=t[rt][2]*c%mod*c%mod;
            t[rt][3]=t[rt][3]*c%mod*c%mod*c%mod;
            lazy[rt][1]=lazy[rt][1]*c%mod;
            lazy[rt][2]=lazy[rt][2]*c%mod;
        }
        return;
    }
    int mid=(l+r)/2;
    pushdown(mid-l+1,r-mid,rt);
    if(p<=mid)update(l,mid,p,q,c,op,rt*2);
    if(q>mid)update(mid+1,r,p,q,c,op,rt*2+1);
    for(int i=1;i<=3;i++)t[rt][i]=(t[rt*2][i]+t[rt*2+1][i])%mod;
}
LL query(int l,int r,int p,int q,int op,int rt)
{
    if(p<=l&&r<=q)return t[rt][op];
    int mid=(l+r)/2;
    pushdown(mid-l+1,r-mid,rt);
    LL res=0;
    if(p<=mid)res=(res+query(l,mid,p,q,op,rt*2))%mod;
    if(q>mid)res=(res+query(mid+1,r,p,q,op,rt*2+1))%mod;
    return res;
}
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        if(n==0&&m==0)break;
        build(1,n,1);
        int op,l,r,x;
        while(m--)
        {
            scanf("%d%d%d%d",&op,&l,&r,&x);
            if(op!=4)update(1,n,l,r,x,op,1);
            else printf("%lld\n",query(1,n,l,r,x,1));
        }
    }
    return 0;
}
posted @ 2020-03-11 00:39  灰灰烟影  阅读(125)  评论(0编辑  收藏  举报