智乃酱的cube(线段树维护)



智乃酱有n个cube(立方体),一开始,这些立方体的长宽高均为1,也就是它们的体积都为1×1×1=1,并且这些立方体从1到n排成一排。
接下来智乃酱将要进行m次操作。智乃酱可以将l到r这个区间内所有的立方体某个维度增加a,或者向你询问从l到r中所有立方体的体积之和。
由于这个数字比较大,所以每次查询时你只用输出从l到r中所有立方体的体积之和mod 10^9+7后的结果即可。

链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
 

输入描述:

第一行输入两个正整数n,m(1≤n≤10^5,1≤m≤4×10^5)表示区间的长度与操作的数目。
接下来m行,每行首先输入一个字符表示操作的类型。
当输入的字符为′x′时,还需输入三个整数l,r,a(1≤l≤r≤n,1≤a≤10^9)表示对l到r中所有立方体的x轴上的边的边长增加a。
当输入的字符为′y′时,还需输入三个整数l,r,a(1≤l≤r≤n,1≤a≤10^9)表示对l到r中所有立方体的y轴上的边的边长增加a。
当输入的字符为′z′时,还需输入三个整数l,r,a(1≤l≤r≤n,1≤a≤10^9)l,r,a表示对l到r中所有立方体的z轴上的边的边长增加a{a}a。
当输入的字符为′q′时,还需输入两个整数l,r(1≤l≤r≤n)l表示查询l到r中所有立方体的体积之和mod 10^9+7后的结果。

输入保证至少进行了一次查询操作。

输出描述:

对于每个查询操作,输出l到r中所有立方体的体积之和mod 10^9+7后的结果。

示例1

输入

5 9
x 1 3 1
y 2 4 1
q 1 5
z 3 5 1
q 1 5
x 1 5 1
y 1 5 1
z 1 5 1
q 1 5

输出

13
20
87

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+10;
const int mod=1e9+7;
int n,m;
int add(int a,int b)
{
    return (a+b)%mod;
}
int sub(int a,int b)
{
    return ((a-b)%mod+mod)%mod;
}
int mul(int a,int b)
{
    return a*b%mod;
}
struct node
{
    int lza,lzb,lzc;
    int x,y,z,xy,xz,yz,xyz;
} t[N*4];
void pushdown(int i,int l,int r)
{
    if(t[i].lza)
    {
        int k=t[i].lza;
        int mid=(l+r)>>1;
        int f1=mid-l+1,f2=r-mid;

        t[i<<1].xyz=add(t[i<<1].xyz,mul(t[i<<1].yz,k));
        t[i<<1|1].xyz=add(t[i<<1|1].xyz,mul(t[i<<1|1].yz,k));

        t[i<<1].xy=add(t[i<<1].xy,mul(t[i<<1].y,k));
        t[i<<1|1].xy=add(t[i<<1|1].xy,mul(t[i<<1|1].y,k));

        t[i<<1].xz=add(t[i<<1].xz,mul(t[i<<1].z,k));
        t[i<<1|1].xz=add(t[i<<1|1].xz,mul(t[i<<1|1].z,k));

        t[i<<1].x=add(t[i<<1].x,mul(f1,k));
        t[i<<1|1].x=add(t[i<<1|1].x,mul(f2,k));

        t[i<<1].lza=add(t[i<<1].lza,k);
        t[i<<1|1].lza=add(t[i<<1|1].lza,k);


        t[i].lza=0;
        //return;
    }
    if(t[i].lzb)
    {
        int k=t[i].lzb;
        int mid=(l+r)>>1;
        int f1=mid-l+1,f2=r-mid;

        t[i<<1].xyz=add(t[i<<1].xyz,mul(t[i<<1].xz,k));
        t[i<<1|1].xyz=add(t[i<<1|1].xyz,mul(t[i<<1|1].xz,k));

        t[i<<1].xy=add(t[i<<1].xy,mul(t[i<<1].x,k));
        t[i<<1|1].xy=add(t[i<<1|1].xy,mul(t[i<<1|1].x,k));

        t[i<<1].yz=add(t[i<<1].yz,mul(t[i<<1].z,k));
        t[i<<1|1].yz=add(t[i<<1|1].yz,mul(t[i<<1|1].z,k));


        t[i<<1].y=add(t[i<<1].y,mul(f1,k));
        t[i<<1|1].y=add(t[i<<1|1].y,mul(f2,k));

        t[i<<1].lzb=add(t[i<<1].lzb,k);
        t[i<<1|1].lzb=add(t[i<<1|1].lzb,k);


        t[i].lzb=0;
        //return;
    }
    if(t[i].lzc)
    {
        int k=t[i].lzc;
        int mid=(l+r)>>1;
        int f1=mid-l+1,f2=r-mid;

        t[i<<1].xyz=add(t[i<<1].xyz,mul(t[i<<1].xy,k));
        t[i<<1|1].xyz=add(t[i<<1|1].xyz,mul(t[i<<1|1].xy,k));

        t[i<<1].yz=add(t[i<<1].yz,mul(t[i<<1].y,k));
        t[i<<1|1].yz=add(t[i<<1|1].yz,mul(t[i<<1|1].y,k));

        t[i<<1].xz=add(t[i<<1].xz,mul(t[i<<1].x,k));
        t[i<<1|1].xz=add(t[i<<1|1].xz,mul(t[i<<1|1].x,k));


        t[i<<1].z=add(t[i<<1].z,mul(f1,k));
        t[i<<1|1].z=add(t[i<<1|1].z,mul(f2,k));

        t[i<<1].lzc=add(t[i<<1].lzc,k);
        t[i<<1|1].lzc=add(t[i<<1|1].lzc,k);


        t[i].lzc=0;
        //return;
    }

}
void pushup(int i)
{
    t[i].x=add(t[i<<1].x,t[i<<1|1].x);
    t[i].y=add(t[i<<1].y,t[i<<1|1].y);
    t[i].z=add(t[i<<1].z,t[i<<1|1].z);
    t[i].xy=add(t[i<<1].xy,t[i<<1|1].xy);
    t[i].xz=add(t[i<<1].xz,t[i<<1|1].xz);
    t[i].yz=add(t[i<<1].yz,t[i<<1|1].yz);
    t[i].xyz=add(t[i<<1].xyz,t[i<<1|1].xyz);
}
void build(int i,int l,int r)
{
    t[i].lza=t[i].lzb=t[i].lzc=0;
    if(l==r)
    {
        t[i].x=t[i].y=t[i].z=t[i].xy=t[i].xz=t[i].yz=t[i].xyz=1;
        return;
    }
    int mid=(l+r)>>1;
    build(i<<1,l,mid);
    build(i<<1|1,mid+1,r);
    pushup(i);
    return;
}
void update(int rt,int l,int r,int L,int R,int type,int val)
{
    if(L<=l&&r<=R)
    {
        if(type==1)
        {
            int k=val;
            int f1=r-l+1;

            t[rt].xyz=add(t[rt].xyz,mul(t[rt].yz,k));

            t[rt].xy=add(t[rt].xy,mul(t[rt].y,k));

            t[rt].xz=add(t[rt].xz,mul(t[rt].z,k));

            t[rt].x=add(t[rt].x,mul(f1,k));

            t[rt].lza=add(t[rt].lza,k);
            return;

        }
        if(type==2)
        {
            int k=val;
            int f1=r-l+1;

            t[rt].xyz=add(t[rt].xyz,mul(t[rt].xz,k));

            t[rt].xy=add(t[rt].xy,mul(t[rt].x,k));

            t[rt].yz=add(t[rt].yz,mul(t[rt].z,k));

            t[rt].y=add(t[rt].y,mul(f1,k));

            t[rt].lzb=add(t[rt].lzb,k);
            return;
        }
        if(type==3)
        {
            int k=val;
            int f1=r-l+1;

            t[rt].xyz=add(t[rt].xyz,mul(t[rt].xy,k));

            t[rt].xz=add(t[rt].xz,mul(t[rt].x,k));

            t[rt].yz=add(t[rt].yz,mul(t[rt].y,k));

            t[rt].z=add(t[rt].z,mul(f1,k));

            t[rt].lzc=add(t[rt].lzc,k);
            return;
        }
        return ;
    }
    pushdown(rt,l,r);
    int mid=(l+r)>>1;
    if(L<=mid) update(rt<<1,l,mid,L,R,type,val);
    if(R>mid)update(rt<<1|1,mid+1,r,L,R,type,val);
    pushup(rt);
    return;
}
int query(int rt,int l,int r,int L,int R)
{
    if(L<=l&&R>=r)
    {
        return t[rt].xyz;
    }
    pushdown(rt,l,r);
    int mid=(l+r)>>1;
    int ans=0;
    if(mid >= R) ans=add(ans,query(rt<<1, l, mid, L, R));
    else if(mid < L) ans=add(ans,query(rt<<1|1, mid + 1, r, L, R));
    else
    {
        ans=add(ans,add(query(rt<<1, l, mid, L, mid),query(rt<<1|1, mid + 1, r, mid + 1, R)));
    }
    return ans;
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>n>>m;
    build(1,1,n);
    for(int i=1; i<=m; i++)
    {
        char c;
        cin>>c;
        int l,r;
        cin>>l>>r;
        if(c=='x')
        {
            int a;
            cin>>a;
            update(1,1,n,l,r,1,a);
        }
        else if(c=='y')
        {
            int a;
            cin>>a;
            update(1,1,n,l,r,2,a);
        }
        else if(c=='z')
        {
            int a;
            cin>>a;
            update(1,1,n,l,r,3,a);
        }
        else
        {
            cout<<query(1,1,n,l,r)<<"\n";
        }
    }
    return 0;
}

  • 0
    点赞
  • 1
    收藏
  • 打赏
    打赏
  • 0
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:数字20 设计师:CSDN官方博客 返回首页
评论

打赏作者

一条小小yu

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值