P4915 帕秋莉的魔导书

$ color{#0066ff}{ 题目描述 }$

魔导书是一种需要钥匙才能看得懂的书,然而只有和书写者同等或更高熟练度的人才能看得见钥匙。因此,每本魔导书都有它自己的等级(a_i),同时它也有自己的知识程度为(w_i),现在我们想要知道,一个等级为(b_i)的生物(...),可以从这些魔导书中得到多少知识。

然而不幸的是,每个生物并不知道自己确切的等级,只有一个等级的大致范围,你需要计算出这个生物获得知识程度的期望值。

(color{#0066ff}{输入格式})

第一行两个正整数(n,m)代表起始书的个数,以及操作的个数。

以下n行,每行两个正整数(a_i)(w_i),代表每本书的等级以及知识程度。

接下来的(m)行,每行2或3个正整数。

操作1: 格式:(1 x y)含义:求等级为([x, y]的)生物能获得的期望知识程度。

操作2: 格式:(2 x y) 含义:图书馆又收入了一本等级为(x),知识程度为(y)的魔导书。

(color{#0066ff}{输出格式})

输出包含若干行整数,即为所有操作1的结果,答案保留4位小数。

(color{#0066ff}{输入样例})

5 5
1 1
2 1
3 1
4 1
5 1
1 2 5
1 1 5
1 3 5
2 1 5
1 1 2

(color{#0066ff}{输出样例})

3.5000
3.0000
4.0000
6.5000

(color{#0066ff}{数据范围与提示})

对于30%的数据,保证(1≤所有输入的数字≤1000)

对于100%的数据,保证(1≤n,m≤100000),对于其他数字,保证在int范围内。(保证运算中所有的数字均在long long范围内)

(color{#0066ff}{题解})

根据题意,询问一的答案显然就是这个区间所有位置的前缀和只和/区间长度

说起区间求和。。。线段树啊

然后,线段树维护前缀和的和。。

这题就是个动态开点的线段树,支持区间修改,区间查询。。。裸了。。

#include<bits/stdc++.h>
#define LL long long
LL in() {
	char ch; LL x = 0, f = 1;
	while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
	for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
	return x * f;
}
const int maxn = 1e5 + 10;
const int inf = 2147483644;
int n, m;
struct Tree {
protected:
	struct node {
		node *ch[2];
		LL val, tag;
		node(LL val = 0, LL tag = 0): val(val), tag(tag) { ch[0] = ch[1] = NULL; }
		void upd() { val = (ch[0]? ch[0]->val : 0) + (ch[1]? ch[1]->val : 0); }
	}*root;
	void dwn(node *o, LL l, LL r) {
		if(!o->ch[0]) o->ch[0] = new node();
		if(!o->ch[1]) o->ch[1] = new node();
		LL mid = (l + r) >> 1;
		o->ch[0]->val += (mid - l + 1) * o->tag;
		o->ch[1]->val += (r - mid) * o->tag;
		o->ch[0]->tag += o->tag;
		o->ch[1]->tag += o->tag;
		o->tag = 0;
	}
	void lazy(node *&o, LL l, LL r, LL ql, LL qr, LL val) {
		if(!o) o = new node();
		if(ql <= l && r <= qr) {
			o->tag += val;
			o->val += 1LL * (r - l + 1) * val;
			return;
		}
		dwn(o, l, r);
		LL mid = (l + r) >> 1;
		if(ql <= mid) lazy(o->ch[0], l, mid, ql, qr, val);
		if(qr > mid) lazy(o->ch[1], mid + 1, r, ql, qr, val);
		o->upd();
	}
	LL query(node *&o, LL l, LL r, LL ql, LL qr, LL tag) {
		if(!o) return 0;
		if(ql <= l && r <= qr) return o->val + 1LL * (r - l + 1) * tag;
		LL ans = 0;
		LL mid = (l + r) >> 1;
		dwn(o, l, r);
		if(ql <= mid) ans += query(o->ch[0], l, mid, ql, qr, tag + o->tag);
		if(qr > mid) ans += query(o->ch[1], mid + 1, r, ql, qr, tag + o->tag);
		return ans;
	}
public:
	void lazy(LL l, LL r, LL val) { lazy(root, 1, inf, l, r, val); }
	LL query(LL l, LL r) { return query(root, 1, inf, l, r, 0); }
}s;
int main() {
	n = in(), m = in();
	LL x, y;
	for(int i = 1; i <= n; i++) {
		x = in(), y = in();
		s.lazy(x, inf, y);
	}
	while(m --> 0) {
		if(in() & 1) x = in(), y = in(), printf("%.4f
", (double)s.query(x, y) / (double)(y - x + 1));
		else x = in(), y = in(), s.lazy(x, inf, y);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/olinr/p/10526089.html