Codeforces Round #351 (VK Cup 2016 Round 3, Div. 1 Edition) C E (斜率优化. 概率)

15 篇文章 1 订阅

Levels and Regions


题意:有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]);
}


Bear and Destroying Subtrees


题意:有一颗树,每条边被删的概率为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;
		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值