[bzoj5483][Usaco2018 Dec]Balance Beam_凸包_概率期望
bzoj5483 Usaco2018Dec Balance Beam
题目链接:https://lydsy.com/JudgeOnline/problem.php?id=5483
数据范围:略。
题解:
首先有一个模型,就是长度为$L$的线段,$f_i$表示这个点每次有$\frac{1}{2}$的几率向左,$\frac{1}{2}$的几率向右。走到端点会掉下去的话,走到右端点的概率。
我们发现:$f_i=\frac{f_{i-1}+f_{i+1}}{2}$,是一个等差数列。
然后,$f_0 = 0, f_L=1$,所以$f_i=\frac{L-i}{L}$。
接着,我们对于每个点$i$,设置一个左侧停止点设置一个右侧停止点的话,就可以根据模型求出答案。
停止点,就是把点$(j,a_j)$放进平面的上凸包,然后$i$在凸包上对应的线段的两个端点即可。
代码:
#include <bits/stdc++.h> #define N 100010 using namespace std; typedef long long ll; char *p1, *p2, buf[100000]; #define nc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1 ++ ) int rd() { int x = 0; char c = nc(); while (c < 48) { c = nc(); } while (c > 47) { x = (((x << 2) + x) << 1) + (c ^ 48), c = nc(); } return x; } ll a[N], st[N], l[N], r[N], top; int main() { int n = rd(); for (int i = 1; i <= n; i ++ ) { a[i] = rd(); } st[ ++ top] = 0, st[ ++ top] = 1; for (int i = 2; i <= n + 1; i ++ ) { // st[top - 1], st[top], i // \frac{a[st[top]] - a[st[top - 1]]}{st[top] - st[top - 1]} < \frac{a[i] - a[st[top]]}{i - st[top]} // \Rightleftarrow (a[st[top]] - a[st[top - 1]]) * (i - st[top]) < (a[i] - a[st[top]]) * (st[top] - st[top - 1]) while (top >= 2 && (ll)(a[st[top]] - a[st[top - 1]]) * (i - st[top]) < (ll)(a[i] - a[st[top]]) * (st[top] - st[top - 1])) { top -- ; } st[ ++ top] = i; } for (int i = 1; i < top; i ++ ) { for (int j = st[i] + 1; j < st[i + 1]; j ++ ) { l[j] = st[i], r[j] = st[i + 1]; } l[st[i]] = st[i], r[st[i]] = st[i]; } for (int i = 1; i <= n; i ++ ) { ll ans = 0; if (l[i] == r[i]) { ans = (ll)a[i] * 100000; } else { ans = (100000 * ((ll)a[l[i]] * (r[i] - i) + (ll)a[r[i]] * (i - l[i]))) / (r[i] - l[i]); } printf("%lld\n", ans); } return 0; }
| 欢迎来原网站坐坐! >原文链接<