线段树是一种二叉树结构,能够在lg(n)的复杂度下完成一些计算。
最长见的就是数列求和之类的,而且还能够支持单点修改甚至是区间修改。

线段树的精髓在于懒惰标记,也就是说,在更新的时候,不更新全部子节点,只会打一个标记。

比如说一段区间要加一个值,它不会在每个叶子节点加上相应数值,而是在覆盖需要修改的子节点的区间上加一个tag要加多少,相应的因为要保证上层计算无误,所以要根据自己的孩子数更新自己的sum值。
如果下次要更新这段覆盖的区间的子区间,可以把相应的标记下放。

线段树支持两种操作其实也比较简单,就是考虑两种操作的优先级,根据优先级判断相关节点应该怎么操作。

下面是一个乘和加两种操作的例子。

/*
Sample Input:
6 3
add 0 2 1
mul 2 4 3
sum 0 3
6 3
sum 0 5
mul 0 5 4
sum 0 5

Sample Output:
21

15
60

先输入两个数n和m,代表数组为0,1,2,3,...,n-1,要进行m种操作
下m行,每行开始是一个字符串,代表操作。
add 0 2 1
代表位置为0,1,2的数 都加1
mul 2 4 3
代表位置为2,3,4的数 都乘3
sum 0 3
代表求0,1,2,3的和
*/

/***********************************************\
 |Author: YMC
 |Created Time: 2015-1-20 12:14:28
 |File Name: Multiply_and_Add_zjut1101.cpp
 |Description: 
\***********************************************/
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#define L(rt) (rt<<1)
#define R(rt) (rt<<1|1)
#define mset(l,n) memset(l,n,sizeof(l))
#define rep(i,n) for(int i=0;i<n;++i)
#define maxx(a) memset(a, 0x3f, sizeof(a))
#define zero(a) memset(a, 0, sizeof(a))
#define srep(i,n) for(i = 1;i <= n;i ++)
#define MP make_pair
const int inf=0x3f3f3f3f ;
const double eps=1e-8 ;
const double pi=acos (-1.0);
typedef long long ll;

using namespace std;
const int maxn = 100005;
const int mod = 1000000007;
struct Tree{
    ll sum;
    int l,r;
    ll add,mul;
}tree[maxn << 2];
char op[10];
int n,m;
int a,b;
ll c;
void pushup(int rt) {
    tree[rt].sum = tree[L(rt)].sum + tree[R(rt)].sum;
    tree[rt].sum %= mod;
}
void pushdown(int rt) {
    if(tree[rt].add != 0 || tree[rt].mul != 1){
        tree[L(rt)].sum = tree[L(rt)].sum * tree[rt].mul + tree[rt].add*(tree[L(rt)].r - tree[L(rt)].l + 1);
        tree[L(rt)].sum %= mod;
        tree[L(rt)].mul *= tree[rt].mul;
        tree[L(rt)].mul %= mod;
        tree[L(rt)].add = tree[L(rt)].add * tree[rt].mul + tree[rt].add;
        tree[L(rt)].add %= mod;
        tree[R(rt)].sum = tree[R(rt)].sum * tree[rt].mul + tree[rt].add*(tree[R(rt)].r - tree[R(rt)].l + 1);
        tree[R(rt)].sum %= mod;
        tree[R(rt)].mul *= tree[rt].mul;
        tree[R(rt)].mul %= mod;
        tree[R(rt)].add = tree[R(rt)].add * tree[rt].mul + tree[rt].add;
        tree[R(rt)].add %= mod;
        tree[rt].add = 0;
        tree[rt].mul = 1;
    }
}
void build(int l,int r,int rt) {
    tree[rt].l = l;
    tree[rt].r = r;
    tree[rt].add = 0;
    tree[rt].mul = 1;
    tree[rt].sum = l;
    if(l == r) {
        return ;
    }
    int mid = tree[rt].l + tree[rt].r >> 1;
    build(l,mid,L(rt));
    build(mid + 1, r, R(rt));
    tree[rt].sum = tree[L(rt)].sum + tree[R(rt)].sum;
    tree[rt].sum %= mod;
}
void add(int l,int r,ll v,int rt) {
    if(l <= tree[rt].l && r >= tree[rt].r) {
        tree[rt].add += v;
        tree[rt].add %= mod;
        tree[rt].sum += v*(tree[rt].r - tree[rt].l + 1);
        tree[rt].sum %= mod;
        return ;
    }
    pushdown(rt);
    int mid = tree[rt].l + tree[rt].r >> 1;
    if(mid >= r) {
        add(l,r,v,L(rt));
    } else if(l >= mid + 1) {
        add(l,r,v,R(rt));
    } else {
        add(l,mid,v,L(rt));
        add(mid+1,r,v,R(rt));
    }
    pushup(rt);
}
void mul(int l,int r,ll v,int rt) {
    if(l <= tree[rt].l && r >= tree[rt].r) {
        tree[rt].mul *= v;
        tree[rt].mul %= mod;
        tree[rt].add *= v;
        tree[rt].add %= mod;
        tree[rt].sum *= v;
        tree[rt].sum %= mod;
        return ;
    }
    pushdown(rt);
    int mid = tree[rt].l + tree[rt].r >> 1;
    if(mid >= r) {
        mul(l,r,v,L(rt));
    } else if(l >= mid + 1) {
        mul(l,r,v,R(rt));
    } else {
        mul(l,mid,v,L(rt));
        mul(mid + 1, r, v, R(rt));
    }
    pushup(rt);
} 
ll query(int l,int r,int rt) {
    ll sum = 0;
    if(l <= tree[rt].l && r >= tree[rt].r) {
        return tree[rt].sum % mod;
    }
    pushdown(rt);
    int mid = tree[rt].l + tree[rt].r >> 1;
    if(mid >= r) {
        return query(l,r,L(rt)) % mod;
    } else if(l >= mid + 1) {
        return query(l,r,R(rt)) % mod;
    } else {
        sum += query(l,mid,L(rt));
        sum += query(mid+1,r,R(rt));
        return sum % mod;
    }
}
int main() {
    //freopen("input.txt","r",stdin); 
    while(scanf("%d %d",&n,&m) != EOF) {
        build(0,n,1);
        while(m --) {
            scanf("%s",op);
            if(op[0] == 'a') {
                scanf("%d %d %lld",&a,&b,&c);
                add(a,b,c,1);
            } else if(op[0] == 'm') {
                scanf("%d %d %lld",&a,&b,&c);
                mul(a,b,c,1);
            } else {
                scanf("%d %d",&a,&b);
                printf("%lld\n",query(a,b,1));
            }
        }
        puts("");
    }
    return 0;
}