Problem:
RSQ and RAQ

Write a program which manipulates a sequence A = {a1, a2, . . . , an} with the following operations:

add(s, t, x): add x to as, as+1, ..., at.

getSum(s, t): report the sum of as, as+1, ..., at.

Note that the initial values of ai (i = 1, 2, . . . , n) are 0.

Input

n q
query1
query2
:
queryq

In the first line, n (the number of elements in A) and q (the number of queries) are given. Then, ith query queryi is given in the following format:

0 s t x

or

1 s t

The first digit represents the type of the query. '0' denotes add(s, t, x) and '1' denotes getSum(s, t).

Output

For each getSum operation, print the sum;

Constraints

1 ≤ n ≤ 100000

1 ≤ q ≤ 100000

1 ≤ s ≤ t ≤ n

0 ≤ x < 1000

Sample Input 1

3 5
0 1 2 1
0 2 3 2
0 3 3 3
1 1 2
1 2 3

Sample Output 1

4
8

Sample Input 2

4 3
1 1 4
0 1 4 1
1 1 4

Sample Output 2

0
4

Solution in C# (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using static System.Console;
using static System.Math;

class Program
{
    static void Main()
    {
        SetOut(new System.IO.StreamWriter(OpenStandardOutput()) { AutoFlush = false });
        var N = FastIO.Int();
        var Q = FastIO.Int();
        var d = new SplayTree<long, long>((x, y) => x + y, (x, y, s) => x + y * s, (x, y) => x + y, 0, 0);
        d.Init(N);
        for (int i = 0; i < Q; i++)
        {
            if (FastIO.Int() == 0)
            {
                var s = FastIO.Int() - 1;
                var t = FastIO.Int();
                var x = FastIO.Int();
                d.Update(s, t, x);
            }
            else
            {
                var s = FastIO.Int() - 1;
                var t = FastIO.Int();
                WriteLine(d.Query(s, t));
            }
        }
        Out.Flush();
    }
}

public static class FastIO
{
    static System.IO.Stream str = System.Console.OpenStandardInput();
    const int size = 1024;
    static byte[] buffer = new byte[size];
    static int ptr;
    static int len;

    static byte Read()
    {
        if (ptr == len)
        {
            len = str.Read(buffer, 0, size);
            if (len == 0) return 0;
            ptr = 0;
        }
        return buffer[ptr++];
    }

    public static int Int()
    {
        var c = Read();
        while (c < 0x21)
        {
            c = Read();
        }
        var n = false;
        if (c == '-')
        {
            n = true;
            c = Read();
        }
        var ret = 0;
        while (c > 0x20)
        {
            ret = ret * 10 + c - '0';
            c = Read();
        }
        return n ? -ret : ret;
    }

    public static long Long()
    {
        var c = Read();
        while (c < 0x21)
        {
            c = Read();
        }
        var n = false;
        if (c == '-')
        {
            n = true;
            c = Read();
        }
        var ret = 0L;
        while (c > 0x20)
        {
            ret = ret * 10 + c - '0';
            c = Read();
        }
        return n ? -ret : ret;
    }
}

public class SplayTree<T, E>
{
    class Node
    {
        public T value;
        public int size;
        public T acc;
        public E lazy;
        public bool rev;
        public Node l;
        public Node r;
    }

    Node root;
    Func<T, T, T> F;
    Func<T, E, int, T> G;
    Func<E, E, E> H;
    T TI;
    E EI;
    int count;
    public int Count => count;

    public SplayTree(Func<T, T, T> f, Func<T, E, int, T> g, Func<E, E, E> h, T ti, E ei)
    {
        F = f;
        G = g;
        H = h;
        TI = ti;
        EI = ei;
    }

    public void Init(int length)
    {
        DFSL(ref root, 0, length);
        count = length;
    }

    void DFSL(ref Node p, int l, int r)
    {
        if (l == r) return;
        var k = (l + r) / 2;
        p = new Node { value = TI, size = r - l, acc = TI, lazy = EI };
        DFSL(ref p.l, l, k);
        DFSL(ref p.r, k + 1, r);
    }

    public void Init(int length, T v)
    {
        DFSA(ref root, 0, length, v);
        count = length;
    }

    void DFSA(ref Node p, int l, int r, T v)
    {
        if (l == r) return;
        var k = (l + r) / 2;
        p = new Node { value = v, size = r - l, acc = TI, lazy = EI };
        DFSA(ref p.l, l, k, v);
        DFSA(ref p.r, k + 1, r, v);
        UpdateAcc(p);
    }

    public void Init(T[] array)
    {
        DFS(ref root, 0, array.Length, array);
        count = array.Length;
    }

    void DFS(ref Node p, int l, int r, T[] a)
    {
        if (l == r) return;
        var k = (l + r) / 2;
        p = new Node { value = a[k], size = r - l, acc = TI, lazy = EI };
        DFS(ref p.l, l, k, a);
        DFS(ref p.r, k + 1, r, a);
        UpdateAcc(p);
    }

    int Size(Node t) => t != null ? t.size : 0;

    void UpdateSize(Node t) => t.size = Size(t.l) + Size(t.r) + 1;

    T Acc(Node t) => t != null ? t.acc : TI;

    void UpdateAcc(Node t) => t.acc = F(F(Acc(t.l), t.value), Acc(t.r));

    void PushUp(Node t)
    {
        if (t != null)
        {
            UpdateAcc(t);
            UpdateSize(t);
        }
    }

    void Swap(ref Node l, ref Node r)
    {
        var t = l;
        l = r;
        r = t;
    }

    void PushDown(Node t)
    {
        if (t == null) return;
        if (t.rev)
        {
            t.rev = false;
            Swap(ref t.l, ref t.r);
            if (t.l != null) t.l.rev = !t.l.rev;
            if (t.r != null) t.r.rev = !t.r.rev;
        }
        //if (t.lazy != EI)
        {
            if (t.l != null)
            {
                t.l.lazy = H(t.l.lazy, t.lazy);
                t.l.acc = G(t.l.acc, t.lazy, Size(t.l));
            }
            if (t.r != null)
            {
                t.r.lazy = H(t.r.lazy, t.lazy);
                t.r.acc = G(t.r.acc, t.lazy, Size(t.r));
            }
            t.value = G(t.value, t.lazy, 1);
            t.lazy = EI;
        }
    }

    void Splay(ref Node n, int k)
    {
        Node l = null;
        Node r = null;
        var p = n;

        while (true)
        {
            PushDown(p);
            var i = Size(p.l);
            if (k == i) break;
            if (k > i)
            {
                var pr = p.r;
                var ii = i + Size(pr.l) + 1;
                if (ii == k)
                {
                    p.r = l;
                    l = p;
                    p = pr;

                    k -= i + 1;
                }
                else if (k > ii)
                {
                    PushDown(pr);

                    p.r = pr.l;
                    PushUp(p);
                    pr.l = p;
                    p = pr.r;
                    pr.r = l;
                    l = pr;

                    k -= ii + 1;
                }
                else
                {
                    PushDown(pr);

                    p.r = l;
                    l = p;
                    p = pr.l;
                    pr.l = r;
                    r = pr;

                    k -= i + 1;
                }
            }
            else// k < i
            {
                var pl = p.l;
                var ii = i - Size(pl.r) - 1;
                if (ii == k)
                {
                    p.l = r;
                    r = p;
                    p = pl;
                }
                else if (k > ii)
                {
                    PushDown(pl);

                    p.l = r;
                    r = p;
                    p = pl.r;
                    pl.r = l;
                    l = pl;

                    k -= ii + 1;
                }
                else
                {
                    PushDown(pl);

                    p.l = pl.r;
                    PushUp(p);
                    pl.r = p;
                    p = pl.l;
                    pl.l = r;
                    r = pl;
                }
            }
        }

        var ll = l;
        var rr = r;
        {
            Node s = null;
            while (l != null)
            {
                Node t = l.r;
                l.r = s;
                if (s == null)
                {
                    //l.acc = F(F(Acc(l.l), l.value), p.l == null ? TI : G(p.l.acc, p.l.lazy, p.l.size));// 
                    l.acc = F(F(Acc(l.l), l.value), p.l == null ? TI : p.l.acc);//
                    l.size = Size(l.l) + Size(p.l) + 1;
                }
                else PushUp(l);
                s = l;
                l = t;
            }
            l = s;
        }
        {
            Node s = null;
            while (r != null)
            {
                Node t = r.l;
                r.l = s;
                if (s == null)
                {
                    //r.acc = F(F(p.r == null ? TI : G(p.r.acc, p.r.lazy, p.r.size), r.value), Acc(r.r));//
                    r.acc = F(F(p.r == null ? TI : p.r.acc, r.value), Acc(r.r));//
                    r.size = Size(r.r) + Size(p.r) + 1;
                }
                else PushUp(r);
                s = r;
                r = t;
            }
            r = s;
        }
        if (ll == null) l = p.l;
        else ll.r = p.l;
        if (rr == null) r = p.r;
        else rr.l = p.r;
        p.l = l;
        p.r = r;
        PushUp(p);
        n = p;
    }

    void Merge(out Node t, Node l, Node r)
    {
        if (l == null) t = r;
        else if (r == null) t = l;
        else
        {
            Splay(ref l, l.size - 1);
            l.r = r;
            PushUp(l);
            t = l;
        }
    }

    void Split(Node t, int k, out Node l, out Node r)
    {
        if (t == null)
        {
            l = r = null;
            return;
        }
        if (k == count)
        {
            l = t;
            r = null;
            return;
        }
        Splay(ref t, k);
        l = t.l;
        r = t;
        r.l = null;
        PushUp(r);
    }

    public void Insert(int index, T item)
    {
        Node l, r;
        Split(root, index, out l, out r);
        var n = new Node { value = item, size = 1, acc = TI, lazy = EI };
        Merge(out l, l, n);
        Merge(out root, l, r);
        count++;
    }

    public void RemoveAt(int index)
    {
        Node l, r, _;
        Split(root, index + 1, out l, out r);
        Split(l, index, out l, out _);
        Merge(out root, l, r);
        count--;
    }

    public void RemoveRange(int index, int count)
    {
        Node l, r, _;
        Split(root, index + count, out l, out r);
        Split(l, index, out l, out _);
        Merge(out root, l, r);
        this.count -= count;
    }

    public void Update(int l, int r, E v)
    {
        Node t1, t2, t3;
        Split(root, r, out t2, out t3);
        Split(t2, l, out t1, out t2);
        t2.lazy = H(t2.lazy, v);
        t2.acc = G(t2.acc, v, Size(t2));
        PushDown(t2);
        t2.l = t1;
        PushUp(t2);
        if (t3 == null)
        {
            root = t2;
        }
        else
        {
            t3.l = t2;
            PushUp(t3);
            root = t3;
        }
    }

    public T Query(int l, int r)
    {
        Node t1, t2, t3;
        Split(root, r, out t2, out t3);
        Split(t2, l, out t1, out t2);
        var ret = t2.acc;
        t2.l = t1;
        PushUp(t2);
        if (t3 == null)
        {
            root = t2;
        }
        else
        {
            t3.l = t2;
            PushUp(t3);
            root = t3;
        }
        return ret;
    }

    public void Reverse(int l, int r)
    {
        Node t1, t2, t3;
        Split(root, r, out t2, out t3);
        Split(t2, l, out t1, out t2);
        PushDown(t2);
        t2.l = t1;
        PushUp(t2);
        if (t3 == null)
        {
            root = t2;
        }
        else
        {
            t3.l = t2;
            PushUp(t3);
            root = t3;
        }
    }

    public T Get(int index)
    {
        Splay(ref root, index);
        return root.value;
    }

    public void Clear()
    {
        root = null;
        count = 0;
    }

    public void Rotate(int l, int m, int r)
    {
        Reverse(l, r);
        Reverse(l, l + r - m);
        Reverse(l + r - m, r);
    }
}