题意:有n个等级,要分成k组,求游戏结束的最小期望。游戏中对于一组等级ai,通过这个等级的概率为ai/sumi,blablabla。。。。
#include <iostream> #include <string> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> #include <vector> #include <map> #include <bitset> #include <queue> #pragma comment(linker, "/STACK:102400000,102400000") using namespace std; #define LL long long #define ULL unsigned long long #define eps 1e-9 #define N (200000 + 10) #define M (400000 + 10) #define pii pair<int,int> #define MP make_pair #define inf 0x3f3f3f3f #define lson ll, md, ls #define rson md + 1, rr, rs #define mod 1000000007 int a[N]; double s[N]; double t[N], g[N]; double dp[N][60]; int cnt, head; struct node { double x, y; int id; node() {} node(double x, double y, int id) : x(x), y (y) ,id(id){}; }que[N]; bool check(node a, node b, node c) { return (b.y - a.y) * (c.x - a.x) >= (c.y - a.y) * (b.x - a.x); } void insert(double x, double y, int id) { node tmp = node(x, y, id); while(cnt > 1 && check(que[cnt-2], que[cnt-1], tmp)) --cnt; que[cnt++] = tmp; } bool judge(node a, node b, double x) { return b.y - a.y < x * (b.x - a.x); } int query(double x) { while(head < cnt-1 && judge(que[head], que[head+1], x)) ++head; return que[head].id; } void debug(int l, int r) { double ans = g[r] - g[l-1]; for(int i = l; i <= r; ++i) ans += t[r] * a[i]; printf("l %d r %d ans %.10lf\n", l, r,ans); } int main() { //freopen("in.in", "r", stdin); int n, k; scanf("%d%d", &n, &k); for(int i = 1; i <= n; ++i) { scanf("%d", &a[i]), s[i] = s[i-1] + a[i]; t[i] = 1.0/a[i] + t[i-1]; g[i] = a[i] * t[i-1] + g[i-1]; } for(int i = 1; i <= n; ++i) dp[i][0] = 1e30; for(int j = 1; j <= k; ++j) { head = 0,cnt = 0; insert(0, 0, 0); for(int i = j-1; i < j; ++i) insert(s[i], dp[i][j-1]+g[i], i); for(int i = j; i <= n; ++i) { int k = query(t[i]); dp[i][j] = dp[k][j-1] + s[i] * t[i] - g[i] - s[k] * t[i] + g[k]; insert(s[i], dp[i][j-1]+g[i], i); } } printf("%.10lf\n", dp[n][k]); }
题意:有一颗树,每条边被删的概率为0.5, 求一个子树最大深度的期望,一边建树一边询问
#include <iostream> #include <string> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> #include <vector> #include <map> #include <bitset> #include <queue> #pragma comment(linker, "/STACK:102400000,102400000") using namespace std; #define LL long long #define ULL unsigned long long #define eps 1e-9 #define N (500000 + 10) #define M (400000 + 10) #define pii pair<int,int> #define MP make_pair #define inf 0x3f3f3f3f #define lson ll, md, ls #define rson md + 1, rr, rs #define mod 1000000007 double ans[N][66]; int fa[N]; int tot; const int Max = 50; int main() { int n; scanf("%d", &n); tot = 1; ans[0][0] = 0; for(int i = 1; i<= Max; ++i) ans[0][i] = 1; while(n--) { int op, u; scanf("%d%d", &op, &u); --u; if(op == 2) { double ret = 0; for(int i = 1; i <= Max; ++i) ret += (1 - ans[u][i]); printf("%.10lf\n", ret); } else { fa[tot] = u; ans[tot][0] = 0; for(int i = 1; i <= Max; ++i) ans[tot][i] = 1; double tmp = 0.5; double pre = 0, last = 1;; int v = tot; for(int i = 1; i <= Max; ++i) { pre = ans[u][i]; ans[u][i] /= (0.5 * last + 0.5); ans[u][i] *= (0.5 * ans[v][i-1] + 0.5); last = pre; tmp *= 0.5; if(!u) break; v = u; u = fa[u]; } ++tot; } } }