「2016山东省队集训」 LYK loves jumping
2017-01-05 08:53
549 查看
题目描述
LYK 发现了 n 个点,它想在这些点上跳来跳去。具体地,第 i 个点有一个高度 hi,当 LYK 踩在这个点上方时,这个点会下降 ti,也就是说此时该点高度为 hi-ti,当 LYK 离开该点时,这个点又会恢复到原来的 hi。
现在 LYK 每次可以跳到不超过它当前所在点高度的点(当 ti=0 时,LYK 可以跳到自己所在的点) ,若存在多个这样的点,则 LYK 等概率随机挑选一个点并跳到那个点,若不存在这样的点,则 LYK 会跳到地面。
求 LYK 以第 i 个点为起点时,期望跳几次能够跳到地面(保留 3 位有效数字) 。
若期望步数为无穷,输出 0.000。
设 oo 表示无穷大,X 为一个数,有 oo-X=oo,oo*X=oo,oo/X=oo,oo+X=oo。
输入格式(jumping.in)
第一行输入一个数 n,表示有 n 个点。第二行输入 n 个数,表示 hi。
第三行输入 n 个数,表示 ti。
输出格式(jumping.out)
输出一行 n 个数,表示以当前点为起点时,期望跳几次跳到地面(保留 4 位小数) ,若期望次数为无穷,输出“0.000” 。
样例输入
44 2 2 3
0 1 0 0
样例输出
3.8333 1.0000 3.0000 3.5000数据范围
对于 20%的数据 n<=5。对于另外 20%的数据所有 hi 都相等。
对于再另外 20%的数据不存在 ti=0。
对于再再另外 20%的数据 hi 都互不相等。
对于 100%的数据 1<=n,hi<=10^5,0<=ti<=hi。
题解
算法一:高斯消元,只需要列出所有的方程,跑高斯消元即可。
算法二:
因为hi都相等,因此如果ti≠0,那么这个点肯定是终止点,否则一定可以走下去。
因此我们只需要列个方程,直接解出来即可。
算法三:
不存在ti=0,意思就是肯定不存在环。拓扑图上维护下前缀和,直接裸的DP即可。
算法四:
Ans_i=Ans_i*cnt/tot+sum/tot+1,cnt为和当前点h一样t是0的点的个数(若当前点t不为0,则cnt=0),tot是当前点能走到的点的个数,sum是当前点能走到的点的答案和。然后化简一下,得到Ans_i=(sum+tot)/(tot-cnt),于是我们先按照h升序排序,再按照t降序排序,用个树状数组维护一下前缀和(sum),然后计算答案即可。复杂度O(NlogN)。
题外话,蒟蒻写cmp的时候一开始>写成了>=于是不知为啥re、wa。。。跑完一遍n的值还改了。。。
代码
#include <cstdio> #include <algorithm> using namespace std; struct Data { int h, t, id; double ans; } a[100005]; int n, maxh = -1; const double INF = 1.0 / 0.0; double c[100005]; bool cmpht(Data x, Data y) { return x.h < y.h || (x.h == y.h && x.t > y.t); } bool cmpid(Data x, Data y) { return x.id < y.id; } void change(int pos, double val) { for (int i = pos; i <= maxh; i += i & -i) c[i] += val; } double query(int pos) { double ret = 0; for (int i = pos; i; i -= i & -i) ret += c[i]; return ret; } int cnt[100005]; int main() { scanf("%d", &n); for (int i = 1; i <= n; ++i) { scanf("%d", &a[i].h); cnt[a[i].h] ++; maxh = max(maxh, a[i].h); } for (int i = 1; i <= maxh; ++i) cnt[i] += cnt[i - 1]; for (int i = 1; i <= n; ++i) scanf("%d", &a[i].t); for (int i = 1; i <= n; ++i) a[i].id = i; sort(a+1,a+n+1,cmpht); int nowh = 1; double Ans; for (int i = 1; i <= n;) { if (a[i].t == 0) { int j; for (j = i + 1; a[i].h == a[j].h && a[j].t == 0 && j <= n; ++j); --j; if (cnt[a[i].h] == 0) Ans = 1; else Ans = (query(a[i].h - a[i].t) + cnt[a[i].h]) / (cnt[a[i].h] - (j - i + 1)); for (int k = i; k <= j; ++k) a[k].ans = Ans; change(a[i].h, Ans * (j - i + 1)); i = j + 1; } else { if (cnt[a[i].h - a[i].t] == 0) Ans = 1; else Ans = (query(a[i].h - a[i].t) + cnt[a[i].h - a[i].t]) / (cnt[a[i].h - a[i].t]); a[i].ans = Ans; change(a[i].h, Ans); ++i; } } sort(a+1, a+1+n, cmpid); for (int i = 1; i <= n; ++i) if (a[i].ans == INF) a[i].ans = 0; for (int i = 1; i <= n; ++i) printf("%.4lf ", a[i].ans); }
4000
相关文章推荐
- MySQL 实现树的遍历详解及简单实现示例
- android不用context弹dialog
- 程序设计实训报告 项目1.1
- linux线程的取消(终止)方法
- 单目视觉ADAS的技术与体验升级之路|硬创公开课
- Commvault踏上数据管理“新长征”
- Cocos2d-x 3.x 图形学渲染系列四
- Cocos2d-x 3.x 图形学渲染系列四
- Merge K Sorted Arrays
- linux udev 自动挂载 SD卡/U盘
- xmind8
- Android省市区三级联动控件使用方法实例讲解
- 为什么说深度学习和机器学习截然不同?
- android 6.0 不能搜索Ble设备
- 【Java每日一题】20170105
- 「2016湖南集训」 猜测 guess
- php 5.4 全新的代码复用Trait详解
- 【Java每日一题】20170105
- airplane game
- Unity发布之去掉启动画面