动态开点,空间尽可能开大些
对于标志与坐标的操作,优先级 旋转 > 乘法 > 加法
#include<bits/stdc++.h>
using namespace std;
#define _rep(i, x, y) for(int i = (int)x; i < (int)y; ++i)
#define _dep(i,x,y) for(int i = (int)x; i > (int)y; i--)
#define PII pair<int,int>
#define eb emplace_back
#define pb push_back
#define fi first
#define se second
#define PQ priority_queue
#define lb lower_bound
#define ub upper_bound
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
typedef long long ll;
typedef vector<int> VI;
typedef vector<VI> VII;
typedef vector<ll> VL;
typedef vector<vector<ll>> VLL;
constexpr int KINF = 0x3f3f3f3f;
constexpr double eps = 1e-7;
namespace Seg{
#define LC(x) tr[x].lc
#define RC(x) tr[x].rc
#define _mov(x) tr[x].mov_tag
struct node{
ll poi[3], tag[3], tag2[3] = {1, 1, 1};// 加法标记与乘法标记
int lc, rc, mov_tag = 0;
};
constexpr static int N = 500e6/sizeof(struct node);// 500MB(尽可能拉满)
constexpr static int L = 1, R = 1e9;
constexpr static int mod = 1e9 + 7;
struct node tr[N];
ll cnt = 1;
void pushup(int o){
_rep(i, 0, 3) tr[o].poi[i] = tr[LC(o)].poi[i] + tr[RC(o)].poi[i] % mod;
}
void upd(int o, int l, int r, ll* a, ll* b, int _mv){// 更新信息
// 数值和标记都先旋转再乘后加
(_mov(o) += _mv) %= 3;
if(_mv){
int k = _mv;
k %= 3;
while(k --){// 旋转操作
swap(tr[o].tag[0], tr[o].tag[1]);
swap(tr[o].tag[1], tr[o].tag[2]);
swap(tr[o].tag2[0], tr[o].tag2[1]);
swap(tr[o].tag2[1], tr[o].tag2[2]);
swap(tr[o].poi[0], tr[o].poi[1]);
swap(tr[o].poi[1], tr[o].poi[2]);
}
}
if(b[0] != 1){
_rep(i, 0, 3) (tr[o].poi[i] *= b[i]) %= mod;
_rep(i, 0, 3) (tr[o].tag[i] *= b[i]) %= mod;
_rep(i, 0, 3) {
if(!tr[o].tag2[i]) tr[o].tag2[i] = b[i];
else (tr[o].tag2[i] *= b[i]) %= mod;
}
}
if(a[0]){
_rep(i, 0, 3) (tr[o].poi[i] += (a[i] * (r - l + 1) % mod)) %= mod;
_rep(i, 0, 3) (tr[o].tag[i] += a[i]) %= mod;
}
}
void pushdown(int o, int l, int r){
if(!LC(o)) LC(o) = ++ cnt;
if(!RC(o)) RC(o) = ++ cnt;// 动态开点
int mid = (l + r) >> 1;
// 标记积累到子树
upd(LC(o), l, mid, tr[o].tag, tr[o].tag2, tr[o].mov_tag);
upd(RC(o), mid + 1, r, tr[o].tag, tr[o].tag2, tr[o].mov_tag);
// 该树标记清零
tr[o].mov_tag = 0;
_rep(i, 0, 3) tr[o].tag[i] = 0;
_rep(i, 0, 3) tr[o].tag2[i] = 1;//因为是乘法,所以置为1
return;
}
void add(int lx, int rx, ll* a, int o = 1, int l = L, int r = R){
if(lx > r || rx < l) return ;
if(l >= lx && r <= rx){
ll b[3] = {1, 1, 1};
upd(o, l, r, a, b, 0);
return;
}
int mid = (l + r) >> 1;
pushdown(o, l, r);
add(lx, rx, a, LC(o), l, mid);
add(lx, rx, a, RC(o), mid + 1, r);
pushup(o);
return;
}
void mul(int lx, int rx, ll* a, int o = 1, int l = L, int r = R){
if(lx > r || rx < l) return ;
if(l >= lx && r <= rx){
ll b[3] = {0, 0, 0};
upd(o, l, r, b, a, 0);
return;
}
int mid = (l + r) >> 1;
pushdown(o, l, r);
mul(lx, rx, a, LC(o), l, mid);
mul(lx, rx, a, RC(o), mid + 1, r);
pushup(o);
return;
}
void rotate(int lx, int rx, int o = 1, int l = L, int r = R){
if(lx > r || rx < l) return ;
if(l >= lx && r <= rx){
ll a[3] = {0, 0, 0};
ll b[3] = {1, 1, 1};
upd(o, l, r, a, b, 1);
return;
}
int mid = (l + r) >> 1;
pushdown(o, l, r);
rotate(lx, rx, LC(o), l, mid);
rotate(lx, rx, RC(o), mid + 1, r);
pushup(o);
return;
}
VL query(int lx, int rx, int o = 1, int l = L, int r = R){
if(l >= lx && r <= rx) {
VL res(3, 0);
_rep(i, 0, 3) res[i] = tr[o].poi[i];
return res;
}
int mid = (l + r) >> 1;
pushdown(o, l, r);
VL res(3, 0);
if(lx <= mid){
VL tmp = query(lx, rx, LC(o), l, mid);
_rep(i, 0, 3) res[i] += tmp[i];
}
if(rx > mid){
VL tmp = query(lx, rx, RC(o), mid + 1, r);
_rep(i, 0, 3) (res[i] += tmp[i]) %= mod;
}
return res;
}
};
int main(){
ios::sync_with_stdio(false); cin.tie(0);
int n, m;
cin >> n >> m;
_rep(i, 0, m){
int op;
cin >> op;
if(op == 1){
int l, r, x, y, z;
cin >> l >> r >> x >> y >> z;
ll a[3] = {x, y, z};
Seg::add(l, r, a);
}
else if(op == 2){
int l, r, k;
cin >> l >> r >> k;
ll a[3] = {k, k, k};
Seg::mul(l, r, a);
}
else if(op == 3){
int l, r;
cin >> l >> r;
Seg::rotate(l, r);
}
else{
int l, r;
cin >> l >> r;
VL tmp = Seg::query(l, r);
ll ans = 0;
_rep(i, 0, 3)
(ans += (tmp[i] * tmp[i] % Seg::mod)) %= Seg::mod;
cout << ans << endl;
}
}
return 0;
}