1. 程式人生 > 實用技巧 >Mushroom Gnomes - 2 【CodeForces - 139E】

Mushroom Gnomes - 2 【CodeForces - 139E】

傳送門

題目大意:一條水平直線上有樹和蘑菇,已知每顆樹的座標,高度和向左,向右傾倒的概率,已知蘑菇的座標和該蘑菇的價值,求蘑菇價值總和的期望值。

思路:可以知道一顆樹的傾倒可以看做一個區間的概率更新,我們可以離散化蘑菇的座標點,然後區間更新該區間所有蘑菇的概率,然後遍歷所有蘑菇的期望值。

這裡我們可以發現,我們不需要用到區間更新的lazy標記,嚴格來說不需要用到lazy標記的下壓操作,因為我們是單點求值,一路找點時,直接概率相乘就行。

  1 #include <cstdio>
  2 #include <iostream>
  3 #include <algorithm>
  4
#include <cstring> 5 #include <vector> 6 #include <set> 7 #include <queue> 8 9 using namespace std; 10 11 #define ll long long 12 #define pb push_back 13 #define fi first 14 #define se second 15 #define lson(rt) (rt << 1) 16 #define rson(rt) (rt << 1 | 1) 17
18 const int N = 1e5 + 10; 19 struct node 20 { 21 int rt, l, r; 22 double p; 23 int mid() { return (l + r) >> 1; } 24 inline void init(int l1, int r1) { l = l1; r = r1; p = 1; } 25 }tree[N << 2]; 26 int b[N], v[N]; 27 28 void Build(int rt, int l, int r) 29 {
30 tree[rt].init(l, r); 31 if(l == r) return ; 32 Build(lson(rt), l, tree[rt].mid()); 33 Build(rson(rt), tree[rt].mid() + 1, r); 34 } 35 36 void Update(int rt, int l, int r, int lrank, int rrank, double p) 37 { 38 if(lrank <= l && r <= rrank) { 39 //printf("l = %d r = %d\n", l, r); 40 //printf("before rate = %.10f\n", tree[rt].p); 41 tree[rt].p *= p; 42 //printf("after rate = %.10f\n", tree[rt].p); 43 return ; 44 } 45 46 if(tree[rt].mid() >= rrank) Update(lson(rt), l, tree[rt].mid(), lrank, rrank, p); 47 else if(tree[rt].mid() < lrank) Update(rson(rt), tree[rt].mid() + 1, r, lrank, rrank, p); 48 else { 49 Update(lson(rt), l, tree[rt].mid(), lrank, rrank, p); 50 Update(rson(rt), tree[rt].mid() + 1, r, lrank, rrank, p); 51 } 52 53 } 54 55 double Query(int rt, int l, int r, int rank) 56 { 57 if(l == r) return tree[rt].p; 58 59 if(tree[rt].mid() >= rank) return tree[rt].p * Query(lson(rt), l, tree[rt].mid(), rank); 60 else return tree[rt].p * Query(rson(rt), tree[rt].mid() + 1, r, rank); 61 } 62 63 void solve() 64 { 65 int n, m; 66 while(~scanf("%d%d", &n, &m)) { 67 68 vector<pair<int, int > > ld, rd; 69 vector<int > lp, rp; 70 for(int i = 1; i <= n; ++i) { 71 int a, h, l, r; 72 scanf("%d%d%d%d", &a, &h, &l, &r); 73 ld.pb(make_pair(a - h, a - 1)); 74 rd.pb(make_pair(a + 1, a + h)); 75 lp.pb(l); 76 rp.pb(r); 77 } 78 79 vector<int > rank; 80 for(int i = 1; i <= m; ++i) { 81 scanf("%d%d", b + i, v + i); 82 rank.pb(b[i]); 83 } 84 85 sort(rank.begin(), rank.end()); 86 rank.erase(unique(rank.begin(), rank.end()), rank.end()); 87 //for(auto x : rank) cout << x << " "; 88 //cout << endl; 89 int len = rank.size(); 90 Build(1, 1, m); 91 //cout << "86 lines" << endl; 92 for(int i = 0; i < n; ++i) { 93 //cout << "i = " << i << endl; 94 int lrank = lower_bound(rank.begin(), rank.end(), ld[i].fi) - rank.begin() + 1; 95 int rrank = upper_bound(rank.begin(), rank.end(), ld[i].se) - rank.begin();// + 1; 96 double p1 = 1.0 - lp[i] / 100.0; 97 // printf("lr = %d rr = %d l = %d r = %d p = %.10f\n", ld[i].fi, ld[i].se, lrank, rrank, p1); 98 if(lrank <= rrank) Update(1, 1, len, lrank, rrank, p1); 99 //cout << "93 lines" << endl; 100 lrank = lower_bound(rank.begin(), rank.end(), rd[i].fi) - rank.begin() + 1; 101 rrank = upper_bound(rank.begin(), rank.end(), rd[i].se) - rank.begin();// + 1; 102 p1 = 1.0 - rp[i] / 100.0; 103 //printf("lr = %d rr = %d l = %d r = %d p = %.10f\n", rd[i].fi, rd[i].se, lrank, rrank, p1); 104 if(lrank <= rrank) Update(1, 1, len, lrank, rrank, p1); 105 //cout << "98 lines" << endl; 106 } 107 108 // cout << "100 lines" << endl; 109 double excp = 0; 110 for(int i = 1; i <= m; ++i) { 111 int rankme = lower_bound(rank.begin(), rank.end(), b[i]) - rank.begin() + 1; 112 // printf("rank_me = %d\n", rankme); 113 // printf("rate = %.10f\n", Query(1, 1, m, rankme) ); 114 excp += Query(1, 1, m, rankme) * (double)v[i]; 115 } 116 //printf("rate_root = %.10f\n", tree[1].p); 117 //printf("excp = %.10f\n", excp); 118 printf("%.10f\n", excp); 119 } 120 } 121 122 int main(){ 123 124 solve(); 125 126 return 0; 127 } 128 129 /* 130 3 3 131 2 2 50 50 132 4 2 50 50 133 7 7 50 50 134 3 1 135 5 1 136 6 1 137 138 */