传送门: http://www.lydsy.com/JudgeOnline/problem.php?id=2752

这道题其实想到线段树并不难,而且如果正确的推出了公式写起来也就是有点恶心而已= =实现不太容易出错。但是公式推起来确实比较的酸爽,加上我的公式又比较的迷,然后跑的飞慢= =

这道题对于一个区间的期望,是整个区间的路径和除上区间的路径数目。数目可以O(1), 然后就在线段树中维护这个路径和。考虑区间合并(线段树都是这样= =),那么对于两个区间l, r, 那么路径和首先等于l的路径和加上r路径和,然后对于l中的一段路径,那么它的更新就是这条路径左边点的个数(包括左端点)* r中点的个数 * v,而出了r中的点的个数以外,其余部分作为一个元素up进行维护。 同样右边同理一个down 维护。 同时在更新这两个值的时候还需要维护一个区间和sum= =

然后lazy 标记的下放:sum 直接搞,然后up 和down 都是 * len[区间长度]* (len - 1) * v; 

ans += lazy * (1 * len * + 2 * (len - 1)  + 3 * (len - 3) ... + (len - 1) * 2 + len * 1) = len * (len + 1) * (len + 2) / 6 * lazy

然后就搞搞= = 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

typedef long long qword;
const qword maxn = 101000;

struct node {
    qword up, down, ans, lazy, sum;
    node *l, *r;
}e[maxn * 3]; qword ne = 0;
node* root;

node* build(qword l, qword r) {
    node* now = e + ne ++;
    if(l ^ r) {
        qword mid = (l + r) >> 1;
        now-> l = build(l, mid);
        now-> r = build(mid + 1, r);
    }
    return now;
}

void update(node* x, qword l, qword r, qword mid) {
    if(l ^ r) {
        x-> ans = x-> l-> ans + x-> r-> ans + x-> l-> up * (r - mid) + x-> r-> down * (mid - l + 1);
        x-> sum = x-> l-> sum + x-> r-> sum;
        x-> up = x-> l-> up + x-> r-> up + x-> r-> sum * (mid - l + 1);
        x-> down = x-> l-> down + x-> r-> down + x-> l-> sum * (r - mid);
    }
}

void pushdown(node* x, qword l, qword r) {
    if(x-> l) {
        qword mid = (l + r) >> 1, v = x-> lazy, ln = mid - l + 1, rn = r - mid;
        x-> l-> ans += ln * (ln + 1) / 2 * (ln + 2) / 3 * v;
        x-> r-> ans += rn * (rn + 1) / 2 * (rn + 2) / 3 * v;
        x-> l-> sum += ln * v;
        x-> r-> sum += rn * v;
        x-> l-> up += ln * (ln + 1) / 2 * v;
        x-> r-> up += rn * (rn + 1) / 2 * v;
        x-> l-> down += ln * (ln + 1) / 2 * v;
        x-> r-> down += rn * (rn + 1) / 2 * v;
        x-> l-> lazy += v, x-> r-> lazy += v;
        x-> lazy = 0;
    }
}

void addlazy(node* now, qword l, qword r, qword ls, qword rs, qword v) {
    if(now-> lazy != 0) pushdown(now, l, r);
    if(l == ls && r == rs) {
        qword nn = rs - ls + 1; 
        now-> ans += nn * (nn + 1) / 2 * (nn + 2) / 3 * v;
        now-> sum += nn * v;
        now-> up += nn * (nn + 1) / 2 * v;
        now-> down += nn * (nn + 1) / 2 * v;
        now-> lazy += v;
    }
    else {
        qword mid = (l + r) >> 1;
        if(rs <= mid) addlazy(now-> l, l, mid, ls, rs, v);
        else if(ls > mid) addlazy(now-> r, mid + 1, r, ls, rs, v);
        else addlazy(now-> l, l, mid, ls, mid, v), addlazy(now-> r, mid + 1, r, mid + 1, rs, v);
        update(now, l, r, mid);
    }
}

node ask(node* now, qword l, qword r, qword ls, qword rs) {
    if(now-> lazy != 0) pushdown(now, l, r);
    node ret;
    if(l == ls && r == rs) ret = *now;
    else {
        qword mid = (l + r) >> 1;
        if(rs <= mid) ret = ask(now-> l, l, mid, ls, rs);
        else if(ls > mid) ret = ask(now-> r, mid + 1, r, ls, rs);
        else {
            node lr = ask(now-> l, l, mid, ls, mid);
            node rr = ask(now-> r, mid + 1, r, mid + 1, rs);
            ret.l = &lr, ret.r = &rr;
            update(&ret, ls, rs, mid);
        }
    }
    return ret;
}

qword qword_get() {
    qword x = 0; char c = (char)getchar();
    qword f = 0;
    while(!isdigit(c) && c != '-') c = (char)getchar();
    if(c == '-') c =(char)getchar(), f = 1;
    while(isdigit(c)) {
        x = x * 10 + (qword)(c - '0');
        c = (char)getchar();
    }
    if(f) x = -x;
    return x;
}

qword n, m;

qword gcd(qword a, qword b) {
    return a % b == 0 ? b : gcd(b, a % b);
}

void test(node* now, qword l, qword r) {
    cout << l <<" "<< r <<" "<< now-> ans <<" "<< now-> sum <<" " << now-> up <<" "<< now-> down <<" "<< now-> lazy << endl;
    if(l ^ r) {
        qword mid = (l + r) >> 1;
        test(now-> l, l, mid), test(now-> r, mid + 1, r);
    }
}

void sov() {
    n = qword_get(), m = qword_get();
    root = build(1, n - 1);
    char s[10]; 
    while(m --) {
        scanf("%s", s + 1);
        if(s[1] =='C') {
            qword ls, rs, v; 
            ls = qword_get(); rs = qword_get(); v = qword_get();
            rs --;
            addlazy(root, 1, n - 1, ls, rs, v);
        }
        if(s[1] == 'Q') {
            qword ls, rs; 
            ls = qword_get(), rs = qword_get();
            rs --;
            node ret = ask(root, 1, n - 1, ls, rs);
            qword a = ret.ans;
            qword b = (rs - ls + 1) * (rs - ls + 2) / 2;
            qword g = gcd(a, b);
            printf("%lld/%lld\n", a / g, b / g);
        }
    }
}

int main() {
    //freopen("test.in", "r", stdin);
    //freopen("test.out", "w", stdout);
    sov();
    return 0;
}