Hdu 4578 Transformation(细节很重要) ★

题目大意:n个数(初始为0)m个操作,操作类型有4中,操作1把区间的每个数+a,操作2把区间的每个数*a.,操作3把区间的每个数=a,操作4,查询区间每个数p次方的和(1<=p<=3)


对于=更新操作:如果之前有*和+的标记,那可以忽略到*+操作,直接=操作,这个最简单,sum1=val,sum2=val*val,sum3=val*val*val;

对于*+操作:如果之前有=标记,就不能忽略了,所以pushdown优先考略=操作。 *+操作可以一起(a*x+c).

注意:在*操作更新时,要一起更新+操作,因为(x+c)*a;

 然后对于 (ax+c)^3=a^3*x^3+3*a^2*c*x^2+3*a*c^2*x+c^3,也就是root[t].sum3=a^3*root[t].sum3+3*a^2*c*root[t].sum2+3*a*c^2*root[t].sum1+c^3*(root[t].r-roo[t].l+1);

 同理 root[t].sum2=root[t].sum2*a^2+root[t].sum1*c*2+c^2*(root[t].r-root[t].l+1);    oot[t].sum1=root[t].sum1*a+c*(root[t].r-root[t].l+1);

注意:sum3,sum2,sum1在这个操作中的顺序不能变。

注意还要手写pow,以及pushdown操作,好多细节需要考虑

pushdown操作时,遇到mul就要更新pos<<1 和pos<<1|1的mul和lazy,遇到lazy就要更新pos<<1 和pos<<1|1的lazy

细节啊!!!!

#include <set>
#include <map>
#include <stack>
#include <queue>
#include <deque>
#include <cmath>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define L(i) i<<1
#define R(i) i<<1|1
#define INF  0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-9
#define maxn 100100
#define MOD 1000000007
const long long mod = 10007;
int n,m;
long long a[maxn*10];

struct node
{
    int l,r;
    long long Max,Min;
    long long sum[4],lazy,mul,cover;
} tree[maxn*4];
long long pow(long long a,int b)
{
    long long ans = 1;
    for(int i = 0; i < b; i++)
        ans = ans * a % mod;
    return ans;
}
void pushup(int pos)
{
    if(tree[pos].l == tree[pos].r)
        return;
    for(int i = 1; i < 4; i++)
        tree[pos].sum[i] = (tree[pos<<1].sum[i] + tree[pos<<1|1].sum[i])%mod;
    //tree[pos].Max = max(tree[pos<<1].Max,tree[pos<<1|1].Max);
    //tree[pos].Min = min(tree[pos<<1].Min,tree[pos<<1|1].Min);
}

void pushdown(int pos)
{
    if(tree[pos].l == tree[pos].r)
        return;
    if(tree[pos].cover != -1)
    {
        int l = tree[pos<<1].l,r = tree[pos<<1].r;
        tree[pos<<1].lazy = 0;
        tree[pos<<1].mul = 1;
        tree[pos<<1].cover = tree[pos].cover;
        for(int i = 1; i < 4; i++)
            tree[pos<<1].sum[i] = (long long)(r-l+1)*(long long)pow(tree[pos].cover,i)%mod;
        l = tree[pos<<1|1].l,r = tree[pos<<1|1].r;
        tree[pos<<1|1].lazy = 0;
        tree[pos<<1|1].mul = 1;
        tree[pos<<1|1].cover = tree[pos].cover;
        for(int i = 1; i < 4; i++)
            tree[pos<<1|1].sum[i] = (long long)(r-l+1)*(long long)pow(tree[pos].cover,i)%mod;
        tree[pos].cover = -1;
    }
    if(tree[pos].mul != 1)
    {
        tree[pos<<1].mul = (tree[pos<<1].mul * tree[pos].mul)%mod;
        tree[pos<<1].lazy = (tree[pos<<1].lazy * tree[pos].mul) % mod;
        for(int i = 1; i < 4; i++)
            tree[pos<<1].sum[i] = (tree[pos<<1].sum[i] * (long long)pow(tree[pos].mul,i))%mod;
        tree[pos<<1|1].mul = (tree[pos<<1|1].mul * tree[pos].mul)%mod;
        tree[pos<<1|1].lazy = (tree[pos<<1|1].lazy * tree[pos].mul) % mod;
        for(int i = 1; i < 4; i++)
            tree[pos<<1|1].sum[i] = (tree[pos<<1|1].sum[i] * (long long)pow(tree[pos].mul,i))%mod;
        tree[pos].mul = 1;
    }
    if(tree[pos].lazy)
    {
        int l = tree[pos<<1].l,r = tree[pos<<1].r;
        long long add = tree[pos].lazy;
        tree[pos<<1].lazy = (tree[pos<<1].lazy + tree[pos].lazy)%mod;
        tree[pos<<1].sum[3] = (tree[pos<<1].sum[3]+3*tree[pos<<1].sum[1]*add*add+3*tree[pos<<1].sum[2]*add+(long long)(r-l+1)*add*add*add)%mod;
        tree[pos<<1].sum[2] = (tree[pos<<1].sum[2]+2*tree[pos<<1].sum[1]*add+(long long)(r-l+1)*add*add)%mod;
        tree[pos<<1].sum[1] = (tree[pos<<1].sum[1]+(long long)(r-l+1)*add)%mod;

        l = tree[pos<<1|1].l,r = tree[pos<<1|1].r;
        tree[pos<<1|1].lazy = (tree[pos<<1|1].lazy + tree[pos].lazy)%mod;
        tree[pos<<1|1].sum[3] = (tree[pos<<1|1].sum[3]+3*tree[pos<<1|1].sum[1]*add*add+3*tree[pos<<1|1].sum[2]*add+(long long)(r-l+1)*add*add*add)%mod;
        tree[pos<<1|1].sum[2] = (tree[pos<<1|1].sum[2]+2*tree[pos<<1|1].sum[1]*add+(long long)(r-l+1)*add*add)%mod;
        tree[pos<<1|1].sum[1] = (tree[pos<<1|1].sum[1]+(long long)(r-l+1)*add)%mod;
        tree[pos].lazy = 0;
    }
}

void build(int l,int r,int pos)
{
    tree[pos].l = l;
    tree[pos].r = r;
    for(int i = 0; i < 4; i++)
        tree[pos].sum[i] = 0;
    tree[pos].lazy = 0;
    tree[pos].mul = 1;
    tree[pos].cover = -1;
    if(l == r)
    {
        //scanf("%lld",&tree[pos].sum);
        //tree[pos].Max = tree[pos].sum;
//        tree[pos].Min = tree[pos].sum;
        return;
    }
    int mid = (l+r)/2;
    build(l,mid,pos<<1);
    build(mid+1,r,pos<<1|1);
    //pushup(pos);
}                                                   //建树                                                  //查询操作

void update(int l,int r,int pos,long long add,int choose)
{
    add %= mod;
    if(choose == 1)
    {
        if(tree[pos].l == l && tree[pos].r == r)
        {
            //tree[pos].sum += (r-l+1)*add;
            //tree[pos].Max = add;
//        tree[pos].Min += add;
            tree[pos].sum[3] = (tree[pos].sum[3]+3*tree[pos].sum[1]*add*add+3*tree[pos].sum[2]*add+(long long)(r-l+1)*add*add*add)%mod;
            tree[pos].sum[2] = (tree[pos].sum[2]+2*tree[pos].sum[1]*add+(long long)(r-l+1)*add*add)%mod;
            tree[pos].sum[1] = (tree[pos].sum[1]+(long long)(r-l+1)*add)%mod;
            tree[pos].lazy += add;
            tree[pos].lazy %= mod;
            return;
        }
        pushdown(pos);
        int mid = (tree[pos].l + tree[pos].r) >> 1;
        if(r <= mid)
            update(l,r,pos<<1,add,choose);
        else if(l > mid)
            update(l,r,pos<<1|1,add,choose);
        else if(l <= mid && r > mid)
        {
            update(l,mid,pos<<1,add,choose);
            update(mid+1,r,pos<<1|1,add,choose);
        }
        pushup(pos);
    }
    else if(choose == 2)
    {
        if(tree[pos].l == l && tree[pos].r == r)
        {
            for(int i = 1; i < 4; i++)
                tree[pos].sum[i] = (tree[pos].sum[i] * (long long)pow(add,i))%mod;
            //tree[pos].Max = add;
            //tree[pos].Min += add;
            tree[pos].mul = tree[pos].mul * add % mod;
            tree[pos].lazy = tree[pos].lazy * add % mod;
            return;
        }
        pushdown(pos);
        int mid = (tree[pos].l + tree[pos].r) >> 1;
        if(r <= mid)
            update(l,r,pos<<1,add,choose);
        else if(l > mid)
            update(l,r,pos<<1|1,add,choose);
        else if(l <= mid && r > mid)
        {
            update(l,mid,pos<<1,add,choose);
            update(mid+1,r,pos<<1|1,add,choose);
        }
        pushup(pos);
    }
    else
    {
        if(tree[pos].l == l && tree[pos].r == r)
        {
            for(int i = 1; i < 4; i++)
                tree[pos].sum[i] = (long long)(r-l+1)*(long long)pow(add,i) % mod;
            //tree[pos].Max = add;
            //tree[pos].Min += add;
            tree[pos].lazy = 0;
            tree[pos].mul = 1;
            tree[pos].cover = add;
            return;
        }
        pushdown(pos);
        int mid = (tree[pos].l + tree[pos].r) >> 1;
        if(r <= mid)
            update(l,r,pos<<1,add,choose);
        else if(l > mid)
            update(l,r,pos<<1|1,add,choose);
        else if(l <= mid && r > mid)
        {
            update(l,mid,pos<<1,add,choose);
            update(mid+1,r,pos<<1|1,add,choose);
        }
        pushup(pos);
    }
}                                         //自上而下更新节点

long long query(int l,int r,int pos,int choose)
{
    if(tree[pos].l == l && tree[pos].r == r)
        return tree[pos].sum[choose];
    pushdown(pos);
    int mid = (tree[pos].l+tree[pos].r)>>1;
    if(r <= mid)
        return query(l,r,pos<<1,choose);
    else if(l > mid)
        return query(l,r,pos<<1|1,choose);
    else
        return (query(l,mid,pos<<1,choose) + query(mid+1,r,pos<<1|1,choose))%mod;
}

int main()
{
    int t,n,m,C = 1,num = 0;
    //scanf("%d",&t);
    //freopen("1.txt","r",stdin);
    while(scanf("%d%d",&n,&m) && (n+m))
    {
        build(1,n,1);
        //printf("Case %d:\n",C++);
        while(m--)
        {
            int k,x,y,c;
            scanf("%d%d%d%d",&k,&x,&y,&c);
            if(k == 4)
                //a[num++] = query(x,y,1,c)%mod;
                printf("%lld\n",query(x,y,1,c)%mod);
            else
                update(x,y,1,(long long)c,k);
        }
    }
//    freopen("2.txt","r",stdin);
//    long long l;
//    for(int i = 0; i < num; i++)
//    {
//        scanf("%lld",&l);
//        if(l != a[i])
//            printf("%d %d %lld %lld\n",i,b[i],l,a[i]);
//    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值