帕秋莉的魔导书

龙之吻—水货

2018-10-03 12:50:14

Personal

# 题外话 想到大家被$T5$折磨了那么久,就应该用一道水题结束这场比赛~~其实还是因为我太菜不会出难题~~。 # Solution 考虑暴力 暴力的话是要求出$[l,r]$这个区间每种情况的知识程度和的总和,然后再除以区间长度。 似乎可以直接维护一棵资瓷区间修改,区间查询的权值线段树,不过当时我没想到,就用了下面这种做法。 思考查询$[l,r]$这个区间,等级小于等于$l$的所有书都是可以看的所以直接加入答案,等级大于$r$的书是不可能看到的,就直接不管了,然后我们就会发现,能看等级为$l + 1$的书的情况有$r - l$种,能看等级为$l + 2$的书的情况有$r - l - 1$种...... 之后,实际上就是要求在较短的时间内求出$\sum_{i=l}^ra[i] \times (r - i)$再和前面的加起来就好了。 我的方法是维护两棵权值动态开点线段树,第一棵维护原序列,第二棵维护$a[i] \times (MAX\_INT - i)$。之后加加减减就能得出总和,再除一下就能得到答案了。 ```cpp #include<cstdio> typedef long long ll; typedef double ld; class Node{ private : public : Node *leftchild, *rightchild; int left, right; ll sum; Node(int left, int right) : left(left), right(right), leftchild(NULL), rightchild(NULL), sum(0) {} }; class SegmentTree{ private : Node *root; void Update(Node *now) { now->sum = 0; if (now->leftchild) { now->sum += now->leftchild->sum; } if (now->rightchild) { now->sum += now->rightchild->sum; } } void AddVal(Node *now, int pos, ll val) { if (now->left == now->right) { now->sum += val; return; } int mid = now->left + now->right >> 1; if (pos <= mid) { if (!now->leftchild) { now->leftchild = new Node(now->left, mid); } AddVal(now->leftchild, pos, val); } else { if (!now->rightchild) { now->rightchild = new Node(mid + 1, now->right); } AddVal(now->rightchild, pos, val); } Update(now); } ll Query(Node *now, int l, int r) { if (!now || now->right < l || now->left > r) { return 0; } if (now->left >= l && now->right <= r) { return now->sum; } return Query(now->leftchild, l, r) + Query(now->rightchild, l, r); } public : void Init(int l, int r) { root = new Node(l, r); } void AddVal(int pos, ll val) { AddVal(root, pos, val); } ll Query(int l, int r) { return Query(root, l, r); } }; SegmentTree a, b; int n, m; int main() { freopen("in10.in", "r", stdin); freopen("out10.out", "w", stdout); ll k = (1ll << 31) - 1; scanf("%d %d", &n, &m); a.Init(1, k); b.Init(1, k); for (int i = 1; i <= n; i++) { int x, y; scanf("%d %d", &x, &y); a.AddVal(x, (k - x + 1) * y); b.AddVal(x, y); } for (int i = 1; i <= m; i++) { int op, x, y; scanf("%d %d %d", &op, &x, &y); if (op == 1) { int res = b.Query(1, x); if (x == y) { printf("%.4lf\n", res); continue; } ll sum = a.Query(x + 1, y) - b.Query(x + 1, y) * (k - y); ld ans = (ld)res; ans += (ld)sum / (ld)(y - x + 1); printf("%.4lf\n", ans); } else { a.AddVal(x, (k - x + 1) * y); b.AddVal(x, y); } } return 0; } ```