Codeforces 895E Eyes Closed(线段树)
题目链接 Eyes Closed
题意 两个人玩一个游戏,现在有两种操作:
1、两个人格子挑选一个区间,保证两个的区间不相交。在这两个区间里面各选出一个数,交换这两个数。
2、挑选一个区间,求这个区间的和的期望。
对于第一种操作,先求出两个区间的长度len1和len2,再求出两个区间的期望和s1和s2。
对于第一个区间,我们先把这个区间里的所有数(期望值)乘上(len1−1)/(len1),再加上s2/len1/len2
对于第二个区间,我们先把这个区间里的所有数(期望值)乘上(len2−1)/(len2),再加上s1/len1/len2
线段树维护这两个操作即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | #include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i) #define dec(i, a, b) for (int i(a); i >= (b); --i) #define ls (i << 1) #define rs (i << 1 | 1) #define mid ((L + R) >> 1) #define lson i << 1, L, mid #define rson i << 1 | 1, mid + 1, R typedef long long LL; const int N = 4e5 + 10; double add[N], mul[N], s[N]; int n, q; void pushup( int i){ s[i] = s[ls] + s[rs]; } void pushdown( int i, int L, int R){ s[ls] = mul[i] * s[ls] + add[i] * (mid - L + 1); mul[ls] *= mul[i]; add[ls] = mul[i] * add[ls] + add[i]; s[rs] = mul[i] * s[rs] + add[i] * (R - mid); mul[rs] *= mul[i]; add[rs] = mul[i] * add[rs] + add[i]; add[i] = 0; mul[i] = 1.0; } void build( int i, int L, int R){ add[i] = 0, mul[i] = 1; s[i] = 0; if (L == R){ scanf ( "%lf" , s + i); return ; } build(lson); build(rson); pushup(i); } void add_update( int i, int L, int R, int l, int r, double val){ if (l <= L && R <= r){ s[i] += (R - L + 1) * val; add[i] += val; return ; } pushdown(i, L, R); if (l <= mid) add_update(lson, l, r, val); if (r > mid) add_update(rson, l, r, val); pushup(i); } void mul_update( int i, int L, int R, int l, int r, double val){ if (l <= L && R <= r){ s[i] *= val; mul[i] *= val; add[i] *= val; return ; } pushdown(i, L, R); if (l <= mid) mul_update(lson, l, r, val); if (r > mid) mul_update(rson, l, r, val); pushup(i); } double query( int i, int L, int R, int l, int r){ if (l <= L && R <= r) return s[i]; double ret = 0; pushdown(i, L, R); if (l <= mid) ret += query(lson, l, r); if (r > mid) ret += query(rson, l, r); pushup(i); return ret; } int main(){ scanf ( "%d%d" , &n, &q); build(1, 1, n); while (q--){ int op; scanf ( "%d" , &op); if (op == 1){ int l1, r1, l2, r2; scanf ( "%d%d%d%d" , &l1, &r1, &l2, &r2); double s1 = query(1, 1, n, l1, r1); double s2 = query(1, 1, n, l2, r2); double len1 = r1 - l1 + 1; double len2 = r2 - l2 + 1; mul_update(1, 1, n, l1, r1, 1.0 * (len1 - 1) / len1); mul_update(1, 1, n, l2, r2, 1.0 * (len2 - 1) / len2); add_update(1, 1, n, l1, r1, 1.0 / len1 / len2 * s2); add_update(1, 1, n, l2, r2, 1.0 / len1 / len2 * s1); } else { int l, r; scanf ( "%d%d" , &l, &r); printf ( "%.12f\n" , query(1, 1, n, l, r)); } } return 0; } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步