[关闭]
@VecMD 2016-07-11T21:38:14.000000Z 字数 2141 阅读 1369

CF 494C

@ 题意:个穷人编号,一开始每人都有的财富。现在有个富人捐赠钱,每个富人会选择一个区间的穷人进行资助,每次资助一块钱,有些穷人很有骨气,每次都会有的概率拒掉这次捐助(整个区间的人全都拒掉)。所有的区间满足不相交或者是包含关系。问:所有的捐助完成后,最富的那个人的财富的期望值是多少。

@思路:因为这个区间的特点,我们根据区间的包含关系可以建成一棵树(这里加一个处理,把这个区间作为零号询问插进去作为根节点,被接受的概率为0),然后考虑到期望这种东西是不好转移的,所以我们对概率进行转移。因为最后的答案只是跟最大值有关,所以我们可以这样设计状态:表示第个区间内最大值接受小于等于个捐助的概率。,是第个区间初始财富的最大值,然后就知道根节点,也就是区间的信息,然后根据期望的公式计算即可。

  1. #include <vector>
  2. #include <iomanip>
  3. #include <cstring>
  4. #include <algorithm>
  5. #include <iostream>
  6. const int maxn = 5007,mm=100007;
  7. double dp[maxn][maxn];
  8. int N, M, arr[mm], size[maxn], max[maxn];
  9. std::vector<int> lis[maxn];
  10. struct Node{int l, r, mx;}seg[mm * 4];
  11. void build(int l, int r, int k)
  12. {
  13. seg[k].l = l, seg[k].r = r;
  14. if(l == r) {seg[k].mx = arr[l]; return;}
  15. int mid = (l + r) / 2; build(l, mid, 2*k), build(mid+1, r, 2*k+1);
  16. seg[k].mx = std::max(seg[2*k].mx, seg[2*k+1].mx);
  17. }
  18. int ask(int l, int r, int k){
  19. if(l <= seg[k].l && seg[k].r <= r) return seg[k].mx;
  20. int mid = (seg[k].l + seg[k].r) / 2;
  21. if(r <= mid) return ask(l, r, 2*k);
  22. else if(l > mid) return ask(l , r , 2*k+1);
  23. else return std::max(ask(l, mid, 2*k), ask(mid+1, r, 2*k+1));
  24. }
  25. struct Q
  26. {
  27. int l, r; double p;
  28. Q() { }
  29. Q(int l, int r, double p)
  30. :l(l), r(r), p(p) { }
  31. } q[maxn];
  32. void dfs(int u, int f)
  33. {
  34. for(int i = 0; i < lis[u].size(); i ++){
  35. int v = lis[u][i];
  36. if(v == f) continue;
  37. dfs(v, u);
  38. }
  39. for(int i = 0; i <= M; i ++){
  40. double take = q[u].p, ntake = 1.0 - q[u].p;
  41. for(int j = 0; j < lis[u].size(); j ++){
  42. int v = lis[u][j]; if(v == f) continue;
  43. int t = std::min(M, max[u] - max[v] + i - 1);
  44. if(i != 0) take *= dp[v][t];
  45. t = std::min(M, max[u] - max[v] + i);
  46. ntake *= dp[v][t];
  47. }
  48. if(i != 0) dp[u][i] = take + ntake;
  49. else dp[u][i] = ntake;
  50. }
  51. }
  52. bool cmp(Q &a, Q &b){return a.l < b.l || (a.l == b.l && a.r > b.r);}
  53. int main()
  54. {
  55. std::ios::sync_with_stdio(false);
  56. std::cin >> N >> M;
  57. for(int i = 1; i <= N; i ++){
  58. std::cin >> arr[i];
  59. }
  60. build(1, N, 1);
  61. for(int i = 1; i <= M; i ++){
  62. std::cin >> q[i].l >> q[i].r >> q[i].p;
  63. }
  64. q[0] = Q(1, N, 0.0);
  65. std::sort(q , q + M + 1, cmp);
  66. for(int i = 0; i <= M; i ++) max[i] = ask(q[i].l, q[i].r, 1);
  67. for(int i = 1; i <= M; i ++){
  68. for(int j = i - 1; j >= 0; j --){
  69. if(q[j].l <= q[i].l && q[i].r <= q[j].r){
  70. lis[j].push_back(i); break;
  71. }
  72. }
  73. }
  74. dfs(0, -1);
  75. double ans = 0.0;
  76. ans += dp[0][0] * max[0];
  77. for(int j = 1 ; j <= M; j ++){
  78. ans += (dp[0][j] - dp[0][j - 1]) * (max[0] + j);
  79. }
  80. std::cout << std::fixed << std::setprecision(9) << ans << '\n';
  81. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注