@VecMD
2016-07-11T13:38:14.000000Z
字数 2141
阅读 1561
@ 题意:个穷人编号,一开始每人都有的财富。现在有个富人捐赠钱,每个富人会选择一个区间的穷人进行资助,每次资助一块钱,有些穷人很有骨气,每次都会有的概率拒掉这次捐助(整个区间的人全都拒掉)。所有的区间满足不相交或者是包含关系。问:所有的捐助完成后,最富的那个人的财富的期望值是多少。
@思路:因为这个区间的特点,我们根据区间的包含关系可以建成一棵树(这里加一个处理,把这个区间作为零号询问插进去作为根节点,被接受的概率为0),然后考虑到期望这种东西是不好转移的,所以我们对概率进行转移。因为最后的答案只是跟最大值有关,所以我们可以这样设计状态:表示第个区间内最大值接受小于等于个捐助的概率。,是第个区间初始财富的最大值,然后就知道根节点,也就是区间的信息,然后根据期望的公式计算即可。
#include <vector>#include <iomanip>#include <cstring>#include <algorithm>#include <iostream>const int maxn = 5007,mm=100007;double dp[maxn][maxn];int N, M, arr[mm], size[maxn], max[maxn];std::vector<int> lis[maxn];struct Node{int l, r, mx;}seg[mm * 4];void build(int l, int r, int k){seg[k].l = l, seg[k].r = r;if(l == r) {seg[k].mx = arr[l]; return;}int mid = (l + r) / 2; build(l, mid, 2*k), build(mid+1, r, 2*k+1);seg[k].mx = std::max(seg[2*k].mx, seg[2*k+1].mx);}int ask(int l, int r, int k){if(l <= seg[k].l && seg[k].r <= r) return seg[k].mx;int mid = (seg[k].l + seg[k].r) / 2;if(r <= mid) return ask(l, r, 2*k);else if(l > mid) return ask(l , r , 2*k+1);else return std::max(ask(l, mid, 2*k), ask(mid+1, r, 2*k+1));}struct Q{int l, r; double p;Q() { }Q(int l, int r, double p):l(l), r(r), p(p) { }} q[maxn];void dfs(int u, int f){for(int i = 0; i < lis[u].size(); i ++){int v = lis[u][i];if(v == f) continue;dfs(v, u);}for(int i = 0; i <= M; i ++){double take = q[u].p, ntake = 1.0 - q[u].p;for(int j = 0; j < lis[u].size(); j ++){int v = lis[u][j]; if(v == f) continue;int t = std::min(M, max[u] - max[v] + i - 1);if(i != 0) take *= dp[v][t];t = std::min(M, max[u] - max[v] + i);ntake *= dp[v][t];}if(i != 0) dp[u][i] = take + ntake;else dp[u][i] = ntake;}}bool cmp(Q &a, Q &b){return a.l < b.l || (a.l == b.l && a.r > b.r);}int main(){std::ios::sync_with_stdio(false);std::cin >> N >> M;for(int i = 1; i <= N; i ++){std::cin >> arr[i];}build(1, N, 1);for(int i = 1; i <= M; i ++){std::cin >> q[i].l >> q[i].r >> q[i].p;}q[0] = Q(1, N, 0.0);std::sort(q , q + M + 1, cmp);for(int i = 0; i <= M; i ++) max[i] = ask(q[i].l, q[i].r, 1);for(int i = 1; i <= M; i ++){for(int j = i - 1; j >= 0; j --){if(q[j].l <= q[i].l && q[i].r <= q[j].r){lis[j].push_back(i); break;}}}dfs(0, -1);double ans = 0.0;ans += dp[0][0] * max[0];for(int j = 1 ; j <= M; j ++){ans += (dp[0][j] - dp[0][j - 1]) * (max[0] + j);}std::cout << std::fixed << std::setprecision(9) << ans << '\n';}