题意:
有 n ( n < = 1000000000 ) n(n<=1000000000) n(n<=1000000000)个点,每个点有三维坐标 x , y , z x,y,z x,y,z且每个点坐标为0。有 m ( m < = 40000 ) m(m<=40000) m(m<=40000)个操作:
1 1 1:对 [ L , R ] [L,R] [L,R]内所有点的三维坐标分别增加 a , b , c a,b,c a,b,c;
2 2 2:对 [ L , R ] [L,R] [L,R]内所有点的三维坐标分别乘 k k k;
3 3 3:对 [ L , R ] [L,R] [L,R]内所有点的三维坐标分别变换为 < y , z , x >
4 4 4:对 [ L , R ] [L,R] [L,R]内所有点的三维坐标分别相加之后求平方之和,再mod1,000,000,007;
#define ll long long
#define maxn 500000
struct Node
{
ll sumx,sumy,sumz;//x,y,z三维的答案
ll addx,addy,addz;//x,y,z的加法懒标记
ll mul,ro;//乘法懒标记和旋转懒标记
ll l,r;
ll len;//离散化需要来记录真正的区间长度
}t[maxn<<3];
ll q[maxn][6];//离散化存储
vector<int> v;
ll mod=1000000007;
int n,m;
void build(ll p,ll l,ll r)
{
t[p].l=l;t[p].r=r;t[p].mul=1;
if(l==r)
{
if(l==v.size()-1)t[p].len=0;
else t[p].len=v[l+1]-v[l];
t[p].sumx=t[p].sumy=t[p].sumz=0;return ;
}
ll mid=(l+r)>>1;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
t[p].sumx=(t[p*2].sumx+t[p*2+1].sumx)%mod;
t[p].sumy=(t[p*2].sumy+t[p*2+1].sumy)%mod;
t[p].sumz=(t[p*2].sumz+t[p*2+1].sumz)%mod;
t[p].len=t[p*2].len+t[p*2+1].len;
}
void spread(ll p)
{
if(t[p].l==t[p].r)
{
t[p].mul=1;
t[p].ro=0;
t[p].addx=t[p].addy=t[p].addz=0;
return ;
}
t[p*2].sumx=(((t[p].mul%mod)*t[p*2].sumx)%mod+((t[p*2].len)*(t[p].addx%mod))%mod)%mod;
t[p*2].sumy=(((t[p].mul%mod)*t[p*2].sumy)%mod+((t[p*2].len)*(t[p].addy%mod))%mod)%mod;
t[p*2].sumz=(((t[p].mul%mod)*t[p*2].sumz)%mod+((t[p*2].len)*(t[p].addz%mod))%mod)%mod;
t[p*2+1].sumx=(((t[p].mul%mod)*t[p*2+1].sumx)%mod+((t[p*2+1].len)*(t[p].addx%mod))%mod)%mod;
t[p*2+1].sumy=(((t[p].mul%mod)*t[p*2+1].sumy)%mod+((t[p*2+1].len)*(t[p].addy%mod))%mod)%mod;
t[p*2+1].sumz=(((t[p].mul%mod)*t[p*2+1].sumz)%mod+((t[p*2+1].len)*(t[p].addz%mod))%mod)%mod;
for(ll i=0;i<t[p].ro;i++)//lazy将儿子旋转
{
swap(t[p*2].sumx,t[p*2].sumy);
swap(t[p*2].sumy,t[p*2].sumz);
swap(t[p*2+1].sumx,t[p*2+1].sumy);
swap(t[p*2+1].sumy,t[p*2+1].sumz);
}
ll u,v,w;
u=t[p].addx;v=t[p].addy;w=t[p].addz;
for(ll i=0;i<t[p*2].ro;i++){swap(v,w);swap(u,v);}
t[p*2].addx=((t[p*2].addx%mod)*(t[p].mul%mod)%mod+u%mod)%mod;
t[p*2].addy=((t[p*2].addy%mod)*(t[p].mul%mod)%mod+v%mod)%mod;
t[p*2].addz=((t[p*2].addz%mod)*(t[p].mul%mod)%mod+w%mod)%mod;
u=t[p].addx;v=t[p].addy;w=t[p].addz;
for(ll i=0;i<t[p*2+1].ro;i++){swap(v,w);swap(u,v);}
t[p*2+1].addx=((t[p*2+1].addx%mod)*(t[p].mul%mod)%mod+u%mod)%mod;
t[p*2+1].addy=((t[p*2+1].addy%mod)*(t[p].mul%mod)%mod+v%mod)%mod;
t[p*2+1].addz=((t[p*2+1].addz%mod)*(t[p].mul%mod)%mod+w%mod)%mod;
t[p*2].mul=((t[p*2].mul%mod)*t[p].mul)%mod;
t[p*2+1].mul=((t[p*2+1].mul%mod)*t[p].mul)%mod;
t[p*2].ro=(t[p*2].ro+t[p].ro)%3;
t[p*2+1].ro=(t[p*2+1].ro+t[p].ro)%3;
t[p].addx=t[p].addy=t[p].addz=0;
t[p].mul=1;t[p].ro=0;
}
void rot(ll p,ll l,ll r)
{
if(t[p].r<l||t[p].l>r)return ;
if(t[p].l>=l&&t[p].r<=r)
{
swap(t[p].sumx,t[p].sumy);
swap(t[p].sumy,t[p].sumz);
t[p].ro=(t[p].ro+1)%3;
return ;
}
if(t[p].addx||t[p].addy||t[p].addz||t[p].mul||t[p].ro)
spread(p);
t[p].sumx=(t[p*2].sumx%mod+t[p*2+1].sumx%mod)%mod;
t[p].sumy=(t[p*2].sumy%mod+t[p*2+1].sumy%mod)%mod;
t[p].sumz=(t[p*2].sumz%mod+t[p*2+1].sumz%mod)%mod;
ll mid=(t[p].l+t[p].r)>>1;
if(l<=mid)rot(p*2,l,r);
if(mid<r)rot(p*2+1,l,r);
t[p].sumx=(t[p*2].sumx%mod+t[p*2+1].sumx%mod)%mod;
t[p].sumy=(t[p*2].sumy%mod+t[p*2+1].sumy%mod)%mod;
t[p].sumz=(t[p*2].sumz%mod+t[p*2+1].sumz%mod)%mod;
}
void add(ll p,ll l,ll r,ll a,ll b,ll c)
{
if(t[p].r<l||t[p].l>r)return ;
if(t[p].l>=l&&t[p].r<=r)//加法区间覆盖当前子树
{
t[p].sumx=(t[p].sumx%mod+a*(t[p].len)%mod)%mod;
t[p].sumy=(t[p].sumy%mod+b*(t[p].len)%mod)%mod;
t[p].sumz=(t[p].sumz%mod+c*(t[p].len)%mod)%mod;
for(ll i=0;i<t[p].ro;i++){swap(b,c);swap(a,b);}//有标记将其右移,因为sum已经左移了,这样正好对上
t[p].addx=(t[p].addx%mod+a%mod)%mod;
t[p].addy=(t[p].addy%mod+b%mod)%mod;
t[p].addz=(t[p].addz%mod+c%mod)%mod;
return ;
}
if(t[p].addx||t[p].addy||t[p].addz||t[p].mul||t[p].ro)
spread(p);
t[p].sumx=(t[p*2].sumx%mod+t[p*2+1].sumx%mod)%mod;
t[p].sumy=(t[p*2].sumy%mod+t[p*2+1].sumy%mod)%mod;
t[p].sumz=(t[p*2].sumz%mod+t[p*2+1].sumz%mod)%mod;
ll mid=(t[p].l+t[p].r)>>1;
if(l<=mid)add(p*2,l,r,a,b,c);
if(mid<r)add(p*2+1,l,r,a,b,c);
t[p].sumx=(t[p*2].sumx%mod+t[p*2+1].sumx%mod)%mod;
t[p].sumy=(t[p*2].sumy%mod+t[p*2+1].sumy%mod)%mod;
t[p].sumz=(t[p*2].sumz%mod+t[p*2+1].sumz%mod)%mod;
}
void Mul(ll p,ll l,ll r,ll k)
{
if(t[p].r<l||t[p].l>r)return ;
if(t[p].l>=l&&t[p].r<=r)
{
t[p].addx=((t[p].addx%mod)*(k%mod))%mod;
t[p].addy=((t[p].addy%mod)*(k%mod))%mod;
t[p].addz=((t[p].addz%mod)*(k%mod))%mod;
t[p].mul=((t[p].mul%mod)*(k%mod))%mod;
t[p].sumx=((t[p].sumx%mod)*(k%mod))%mod;
t[p].sumy=((t[p].sumy%mod)*(k%mod))%mod;
t[p].sumz=((t[p].sumz%mod)*(k%mod))%mod;
return ;
}
if(t[p].addx||t[p].addy||t[p].addz||t[p].mul||t[p].ro)
spread(p);
t[p].sumx=(t[p*2].sumx%mod+t[p*2+1].sumx%mod)%mod;
t[p].sumy=(t[p*2].sumy%mod+t[p*2+1].sumy%mod)%mod;
t[p].sumz=(t[p*2].sumz%mod+t[p*2+1].sumz%mod)%mod;
ll mid=(t[p].l+t[p].r)>>1;
if(l<=mid)Mul(p*2,l,r,k);
if(mid<r)Mul(p*2+1,l,r,k);
t[p].sumx=(t[p*2].sumx%mod+t[p*2+1].sumx%mod)%mod;
t[p].sumy=(t[p*2].sumy%mod+t[p*2+1].sumy%mod)%mod;
t[p].sumz=(t[p*2].sumz%mod+t[p*2+1].sumz%mod)%mod;
}
void ask(ll p,ll l,ll r,ll &a,ll &b,ll &c)
{
if(t[p].r<l||t[p].l>r)return ;
if(t[p].l>=l&&t[p].r<=r)
{
a=(t[p].sumx%mod+a)%mod;
b=(t[p].sumy%mod+b)%mod;
c=(t[p].sumz%mod+c)%mod;
return ;
}
if(t[p].addx||t[p].addy||t[p].addz||t[p].mul||t[p].ro)
spread(p);
ll mid=(t[p].l+t[p].r)>>1;
if(l<=mid)ask(p*2,l,r,a,b,c);
if(mid<r)ask(p*2+1,l,r,a,b,c);
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
cin>>q[i][0]>>q[i][1]>>q[i][2];//op,l,r
q[i][2]++;
v.push_back(q[i][1]);v.push_back(q[i][2]);
if(q[i][0]==1)//add
for(int j=3;j<=5;j++)cin>>q[i][j];
else if(q[i][0]==2)cin>>q[i][3];//mul
}
v.push_back(-999);
sort(v.begin(),v.end());//排序保证序列是有序的
v.erase(unique(v.begin(),v.end()),v.end());//将多余的数字去除
for(int i=1;i<=m;i++)
{//二分离散化
q[i][1]=lower_bound(v.begin(),v.end(),q[i][1])-v.begin();
q[i][2]=lower_bound(v.begin(),v.end(),q[i][2])-v.begin();
}
ll ans=v.size()-1;
build(1,1,ans);
for(int i=1;i<=m;i++)
{
if(q[i][0]==1)
{
add(1,q[i][1],q[i][2]-1,q[i][3],q[i][4],q[i][5]);
}
if(q[i][0]==2)
{
Mul(1,q[i][1],q[i][2]-1,q[i][3]);
}
if(q[i][0]==3)
{
rot(1,q[i][1],q[i][2]-1);
}
if(q[i][0]==4)
{
ll ansx=0,ansy=0,ansz=0;
ask(1,q[i][1],q[i][2]-1,ansx,ansy,ansz);
cout<<((ansx%mod)*(ansx%mod)%mod+(ansy%mod)*(ansy%mod)%mod+(ansz%mod)*(ansz%mod))%mod<<endl;
}
}
return 0;
}