NC19991. [HAOI2012]高速公路(ROAD)
描述
输入描述
第一行2个正整数N,M,表示有N个收费站,M次调整或询问
接下来M行,每行将出现以下两种形式中的一种
C l r v 表示将第l个收费站到第r个收费站之间的所有道路的通行费全部增加
v Q l r 表示对于给定的l,r,要求回答小A的问题
所有C与Q操作中保证1 ≤ l < r ≤ N
输出描述
对于每次询问操作回答一行,输出一个既约分数
若答案为整数a,输出a/1
示例1
输入:
4 5 C 1 4 2 C 1 2 -1 Q 1 2 Q 2 4 Q 1 4
输出:
1/1 8/3 17/6
C++11(clang++ 3.9) 解法, 执行用时: 210ms, 内存消耗: 14052K, 提交时间: 2019-03-09 15:37:46
#include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <cctype> #include <algorithm> #define R register #define IN inline #define gc getchar() #define W while #define MX 100050 #define ll long long bool neg; template <class T> IN void in(T &x) { x = 0; R char c = gc; for (; !isdigit(c); c = gc) if(c == '-') neg = true; for (; isdigit(c); c = gc) x = (x << 1) + (x << 3) + c - 48; if(neg) neg = false, x = -x; } struct Node {ll lsum, rsum, sum, len, ans, tag;} tree[MX << 2]; int dot, q; namespace SGT { #define ls (now << 1) #define rs (now << 1 | 1) IN ll F1(ll x) {return x * (x + 1) * (x + 1) / 2;} IN ll F2(ll x) {return x * (x + 1) * (x * 2 + 1) / 6;} IN void pushdown(R int now) { if(tree[now].tag) { ll buf; tree[ls].tag += tree[now].tag; tree[rs].tag += tree[now].tag; buf = tree[ls].len * (tree[ls].len + 1) / 2 * tree[now].tag; tree[ls].lsum += buf, tree[ls].rsum += buf; buf = tree[rs].len * (tree[rs].len + 1) / 2 * tree[now].tag; tree[rs].lsum += buf, tree[rs].rsum += buf; tree[ls].sum += tree[now].tag * tree[ls].len; tree[rs].sum += tree[now].tag * tree[rs].len; tree[ls].ans += (F1(tree[ls].len) - F2(tree[ls].len)) * tree[now].tag; tree[rs].ans += (F1(tree[rs].len) - F2(tree[rs].len)) * tree[now].tag; tree[now].tag = 0; } } IN void pushup(R int now) { tree[now].sum = tree[ls].sum + tree[rs].sum; tree[now].lsum = tree[ls].lsum + tree[rs].lsum + tree[ls].sum * tree[rs].len; tree[now].rsum = tree[ls].rsum + tree[rs].rsum + tree[rs].sum * tree[ls].len; tree[now].ans = tree[ls].ans + tree[rs].ans + tree[ls].len * tree[rs].lsum + tree[rs].len * tree[ls].rsum; } IN Node merge (const Node &x, const Node &y) { Node ret; ret.len = x.len + y.len; ret.sum = x.sum + y.sum; ret.lsum = x.lsum + y.lsum + x.sum * y.len; ret.rsum = x.rsum + y.rsum + y.sum * x.len; ret.ans = x.ans + y.ans + x.len * y.lsum + y.len * x.rsum; return ret; } void build(R int now, R int lef, R int rig) { if(lef == rig) return tree[now].len = 1, void(); int mid = lef + rig >> 1; build(ls, lef, mid), build(rs, mid + 1, rig); tree[now].len = tree[ls].len + tree[rs].len; } void modify(R int now, R int lef, R int rig, R int lb, R int rb, R int del) { if(lef >= lb && rig <= rb) { ll buf; tree[now].tag += del; tree[now].sum += tree[now].len * del; buf = tree[now].len * (tree[now].len + 1) * del / 2; tree[now].lsum += buf, tree[now].rsum += buf; tree[now].ans += (F1(tree[now].len) - F2(tree[now].len)) * del; return; } pushdown(now); int mid = lef + rig >> 1; if(lb <= mid) modify(ls, lef, mid, lb, rb, del); if(rb > mid) modify(rs, mid + 1, rig, lb, rb, del); pushup(now); } Node query(R int now, R int lef, R int rig, R int lb, R int rb) { if(lef >= lb && rig <= rb) return tree[now]; int mid = lef + rig >> 1; pushdown(now); if(rb <= mid) return query(ls, lef, mid, lb, rb); else if(lb > mid) return query(rs, mid + 1, rig, lb, rb); else return merge(query(ls, lef, mid, lb, rb), query(rs, mid + 1, rig, lb, rb)); } #undef ls #undef rs } ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;} int main(void) { char buf[3]; int a, b, c; ll as, g, tar; in(dot), in(q); Node res; SGT::build(1, 1, dot - 1); W (q--) { scanf("%s", buf); if(buf[0] == 'C') { in(a), in(b), in(c); SGT::modify(1, 1, dot - 1, a, b - 1, c); } else { in(a), in(b); res = SGT::query(1, 1, dot - 1, a, b - 1); as = res.ans, tar = 1ll * (b - a) * (b - a + 1) / 2; g = gcd(tar, as), printf("%lld/%lld\n", as / g, tar / g); } } }