HDU 4578 Transformation 【线段树】

题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=4578
在这里插入图片描述


★这题有有3个操作,需要考虑的因素比较多,


题意:

有n个数,4种操作
①:把[ l , r ]的每个数加上c
②:把[ l , r ]的每个数乘上c
③:把[ l , r ]的每个数变成c
④:输出[ l , r ]之间的数的 k次方的和 k=1,2,3


思路:

首先要明确的一点,前三种操作都需要用 懒标记(lazy_tag),故需要三个标记(记为add , mult ,rep)
在询问的时候,可能是区间和、区间平方和、区间立方和,不妨维护这三个值(记为 sum1 ,sum2 ,sum3)

然后问题来了,当标记下传的时候,怎么处理这三个懒标记的关系呢?

初始化的时候add=0, mult=1, rep=0
当进行了操作三,很明显add=0 mult=1
进行操作二时,要 add[k]=add[k]*v%mod; 这样就可以默认每次是 先乘再加的了
然后就是简单的公式推导了 疯狂取模
当 (rep[ k ] != 0)时
sum1=∑( tmp )
sum2=∑( tmp )2
sum3=∑( tmp )3
当 (add[ k ] != 0 || mult[ k ] != 1)时
sum1= ∑(ab+c)
sum2= ∑(ab+c) 2
sum3= ∑(ab+c) 3
把他们化简开就是代码中那段很长的式子了


代码

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<string>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
using namespace std;
const int maxn=1e5+5;
const int sz=1<<10;
const int mod=1e4+7;
const int inf=2e9;
const double eps=1e-8;
const double pi=acos(-1);
typedef long long LL;
int n,m;
int sum1[maxn<<2],sum2[maxn<<2],sum3[maxn<<2];
int add[maxn<<2],mult[maxn<<2],rep[maxn<<2];
template<class t>
inline void read(t &x)
{
    char c; x=1;
    while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
    t res=c-'0';
    while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
    x*=res;
}
void build(int k,int l,int r)
{
    mult[k]=1;
    add[k]=rep[k]=0;
    sum1[k]=sum2[k]=sum3[k]=0;
    if(l==r) return ;
    int mid=l+r>>1;
    build(ls); build(rs);
}
void pushdown(int k,int l,int r,int mid)
{
    if(rep[k]!=0){
        rep[k<<1]=rep[k<<1|1]=rep[k];
        rep[k]=0;
        add[k<<1]=add[k<<1|1]=0;
        mult[k<<1]=mult[k<<1|1]=1;
        int tmp=rep[k<<1];
        sum1[k<<1]=(mid-l+1)*tmp%mod;
        sum2[k<<1]=sum1[k<<1]*tmp%mod;
        sum3[k<<1]=sum2[k<<1]*tmp%mod;
        sum1[k<<1|1]=(r-mid)*tmp%mod;
        sum2[k<<1|1]=sum1[k<<1|1]*tmp%mod;
        sum3[k<<1|1]=sum2[k<<1|1]*tmp%mod;
    }
    if(add[k]!=0||mult[k]!=1){
        add[k<<1]=(add[k<<1]*mult[k]%mod+add[k])%mod;
        add[k<<1|1]=(add[k<<1|1]*mult[k]%mod+add[k])%mod;
        mult[k<<1]=mult[k<<1]*mult[k]%mod;
        mult[k<<1|1]=mult[k<<1|1]*mult[k]%mod;

        int b=mult[k],c=add[k];
        //(a^3*b^3+3*a^2*b^2*c+3*a*b*c^2+c^3)
        //(a^2*b^2+2*a*b*c+c^2)
        sum3[k<<1]=(b*b%mod*b%mod*sum3[k<<1]%mod+3*b%mod*b%mod*c%mod*sum2[k<<1]%mod+3*c%mod*c%mod*b%mod*sum1[k<<1]%mod+(mid-l+1)*c%mod*c%mod*c%mod)%mod;
        sum2[k<<1]=(b*b%mod*sum2[k<<1]%mod+2*b%mod*c%mod*sum1[k<<1]%mod+(mid-l+1)*c%mod*c%mod)%mod;
        sum1[k<<1]=(b*sum1[k<<1]%mod+(mid-l+1)*c%mod)%mod;
        sum3[k<<1|1]=(b*b%mod*b%mod*sum3[k<<1|1]%mod+3*b%mod*b%mod*c%mod*sum2[k<<1|1]%mod+3*c%mod*c%mod*b%mod*sum1[k<<1|1]%mod+(r-mid)*c%mod*c%mod*c%mod)%mod;
        sum2[k<<1|1]=(b*b%mod*sum2[k<<1|1]%mod+2*b%mod*c%mod*sum1[k<<1|1]%mod+(r-mid)*c%mod*c%mod)%mod;
        sum1[k<<1|1]=(b*sum1[k<<1|1]%mod+(r-mid)*c%mod)%mod;

        add[k]=0; mult[k]=1;
    }
}
void update(int k,int l,int r,int x,int y,int v,int type)
{
    if(x<=l&&r<=y){
        v%=mod;
        if(type==1){
            add[k]=(add[k]+v)%mod;
            sum3[k]=(sum3[k]+3*sum2[k]%mod*v%mod+3*sum1[k]%mod*v%mod*v%mod+(r-l+1)*v%mod*v%mod*v%mod)%mod;
            sum2[k]=(sum2[k]+2*sum1[k]%mod*v%mod+(r-l+1)*v%mod*v%mod)%mod;
            sum1[k]=(sum1[k]+v*(r-l+1)%mod)%mod;
        }
        else if(type==2){
            add[k]=add[k]*v%mod;
            mult[k]=mult[k]*v%mod;
            sum1[k]=sum1[k]*v%mod;
            sum2[k]=sum2[k]*v%mod*v%mod;
            sum3[k]=sum3[k]*v%mod*v%mod*v%mod;
        }
        else{
            add[k]=0; mult[k]=1; rep[k]=v;
            sum1[k]=(r-l+1)*v%mod;
            sum2[k]=sum1[k]*v%mod;
            sum3[k]=sum2[k]*v%mod;
        }
        return ;
    }
    int mid=l+r>>1;
    pushdown(k,l,r,mid);
    if(mid>=x) update(ls,x,y,v,type);
    if(mid<y) update(rs,x,y,v,type);
    sum1[k]=(sum1[k<<1]+sum1[k<<1|1])%mod;
    sum2[k]=(sum2[k<<1]+sum2[k<<1|1])%mod;
    sum3[k]=(sum3[k<<1]+sum3[k<<1|1])%mod;
}
int query(int k,int l,int r,int x,int y,int type)
{
    if(x<=l&&r<=y){
        if(type==1) return sum1[k];
        else if(type==2) return sum2[k];
        return sum3[k];
    }
    int mid=l+r>>1;
    pushdown(k,l,r,mid);
    int ans=0;
    if(mid>=x) ans=(ans+query(ls,x,y,type))%mod;
    if(mid<y) ans=(ans+query(rs,x,y,type))%mod;
    return ans;
}
int main()
{
    while(~scanf("%d%d",&n,&m)){
        if(n==0&&m==0) break;
        build(1,1,n);
        int op,a,b,c;
        while(m--){
            read(op); read(a); read(b); read(c);
            if(op==4) printf("%d\n",query(1,1,n,a,b,c));
            else update(1,1,n,a,b,c,op);
        }
    }
    return 0;
}

发布了71 篇原创文章 · 获赞 89 · 访问量 8549

猜你喜欢

转载自blog.csdn.net/weixin_43890662/article/details/101520929