Jumping

Posted hyghb

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Jumping相关的知识,希望对你有一定的参考价值。

Time Limit:1000ms Memory Limit:128MB


题目描述

LYK在玩一个魔法游戏,叫做跳跃魔法。

n个点,每个点有两个属性hiti,表示初始高度,和下降高度。也就是说,它初始时高度为hi,一旦LYK踩在这个点上,由于重力的影响,这个点的高度会下降ti,当LYK离开这个点时,这个点的高度又会回到hi

众所周知的是,跳跃游戏一般是往下跳的,每次LYK可以从一个点跳到任意一个高度不超过它的点,也就是说,当ti=0时,它可以跳到自己本来所在的点。

当没地方可以跳的时候,LYK就会跳到地面,现在LYK想以第i个点为起点,问期望跳多少次能跳到地面。当然i可以是1~n中的任意一个数字。

若期望步数为无穷,输出0.000

oo表示无穷大,X为一个数,有oo-X=oooo*X=oooo/X=oooo+X=oo


输入格式(jumping.in)

第一行输入一个数n,表示有n个点。

第二行输入n个数,表示hi

第三行输入n个数,表示ti


输出格式(jumping.out)

输出一行n个数,表示以当前点为起点时,期望跳几次跳到地面(保留4位小数),若期望次数为无穷,输出“0.0000”


样例输入

4

4 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^50<=ti<=hi

 

其实是个期望的简单题目吧,也很好写,然而考试的时候并没有敢去想正解,谁知道zhw把最简单的放到了t3的位置呢。

对于n<=5,设出每个点期望,高斯消元即可,考试并没敢写,因为从来都没写过。

hi相等的情况,我们发现如果ti不为0,那么期望就是1,ti为0的所有点是等价的,可以列出形如下面这样的式子

f[1]=(f[1]+f[2]+...+f[]+1+1+1)/n+1

f[2]=(f[1]+f[2]+...+f[]+1+1+1)/n+1

括号里面的1是ti不为0的点的期望。

然后化简一下就可以得到一个很简单的式子。还需要判一下无解,也就是所有ti全是0。

不存在ti=0的话,意味着没有无解的情况,我们分别以hi,hi-ti为关键字排序,开两个指针扫一遍数组记录答案即可。(当然只以hi排序,记录前缀和,二分也可以,这也是正解的思路)

hi互不相等我没去做。应该属于正解的一半吧,不需要判断hi相等的情况,只通过统计前缀答案即可。

对于100%的数据。

首先鉴于对部分分的思考,我们先对hi排序。

我们首先考虑无解是什么,有两种情况,一个是它可以跳到无解的点,另外一种是ti=0,并且他无法跳到不完全等价于它本身的点,等价指的是hi,ti均相等。那么对于第一种,我们只需要记录某个前缀是否存在无解的点即可。另外一种也很好判断。

我们来看一下如何转移。

定义b为当ti为0时坐标>=i的和i等价的点的数量,当ti不为0时,b为0。a表示可以向i转移的点的数量,也就是h[a]<=h[i]-t[i]最大的a。

f[i]=(f[1]+f[2]+...+f[a])/(a+b) + f[i]*b/(a+b) +1

然而排序过程中有一些小细节,我们不能单单以hi为关键字排序,因为当hi相等的时候,ti=0的是可以跳到其他点的,而如果那个点在当前点的右边,便会漏算。所以需要以ti为第二关键字从大到小排序,这样的话当处理到ti=0的点时,其右边全是与他等价的点,全部被计算到了f[i]*b/(a+b)中。

设s[a]=(f[1]+f[2]+...+f[a])我们化简一下可得

f[i]=(a+b)/a + s[a]/a

那么只需要在从左往右枚举的过程中维护s[]即可。a可以通过二分查到。

技术分享图片
 1 #include<bits/stdc++.h>
 2 #define dl double
 3 using namespace std;
 4 const int inf=1e5+10;
 5 struct ghb{
 6     int h,t,id;
 7     dl ans;
 8     bool operator < (const ghb &o)const{
 9         return h<o.h || (h==o.h&&t>o.t);
10     }
11 }t[inf];
12 int n;
13 bool is[inf];
14 dl s[inf];
15 int cnt[inf];
16 int get(int x){
17     int l=0,r=x-1;
18     while(l!=r){
19         int mid=(l+r>>1)+1;
20         if(t[mid].h>t[x].h-t[x].t)r=mid-1;
21         else l=mid;
22     }
23     return l;
24 }
25 bool cmp(ghb x,ghb y){
26     return x.id<y.id;
27 }
28 int main()
29 {
30     freopen("jumping.in","r",stdin);
31     freopen("jumping.out","w",stdout);
32     scanf("%d",&n);
33     for(int i=1;i<=n;i++)
34         scanf("%d",&t[i].h);
35     for(int i=1;i<=n;i++)
36         scanf("%d",&t[i].t);
37     for(int i=1;i<=n;i++){
38         t[i].id=i;
39         if(!t[i].t)cnt[t[i].h]++;
40     }
41     sort(t+1,t+n+1);
42     for(int i=1;i<=n;i++){
43         int a=get(i);
44         if(is[a])t[i].ans=0.0;
45         else if(a==0 && t[i].t==0)t[i].ans=0.0;
46         else if(a==0)t[i].ans=1;
47         else if(t[i].t!=0)t[i].ans=s[a]/a+1;
48         else t[i].ans=s[a]/a+(dl)(a+cnt[t[i].h])/a;
49         is[i]=is[i-1];
50         if(t[i].ans==0.0)is[i]=1;
51         s[i]=s[i-1]+t[i].ans;
52         if(t[i].t==0)cnt[t[i].h]--;
53     }
54     sort(t+1,t+n+1,cmp);
55     for(int i=1;i<=n;i++)
56         printf("%.4lf ",t[i].ans);
57     puts("");
58     return 0;
59 }
ac代码

 

技术分享图片
 1 #include<bits/stdc++.h>
 2 #define dl double
 3 using namespace std;
 4 const int inf=1e5+10;
 5 int n,t[inf],h[inf];
 6 dl f[inf];
 7 namespace five_to_six{
 8     struct ghb{
 9         int h1,h2,id;
10     }a[inf],b[inf];
11     bool cmp1(ghb x,ghb y){
12         return x.h1<y.h1;
13     }
14     bool cmp2(ghb x,ghb y){
15         return x.h2<y.h2;
16     }
17     void work(){
18         for(int i=1;i<=n;i++){
19             a[i].id=i;a[i].h1=h[i];a[i].h2=h[i]-t[i];
20             b[i]=a[i];
21         }
22         sort(a+1,a+n+1,cmp1);
23         sort(b+1,b+n+1,cmp2);
24         dl now=0;
25         for(int i=1,j=1;j<=n;j++){
26             while(a[i].h1<=b[j].h2)now+=f[a[i].id],i++;
27             if(i>1)f[b[j].id]=now/(i-1)+1;
28             else f[b[j].id]=1;
29         }
30         for(int i=1;i<=n;i++)
31             printf("%.4lf ",f[i]);
32         puts("");
33     }
34 }
35 int main()
36 {
37     freopen("jumping.in","r",stdin);
38     freopen("jumping.out","w",stdout);
39     scanf("%d",&n);
40     for(int i=1;i<=n;i++){
41         scanf("%d",&h[i]);
42     }
43     bool flg=0;
44     for(int i=1;i<=n;i++){
45         scanf("%d",&t[i]);
46         if(!t[i])flg=1;
47     }
48     if(!flg)
49         five_to_six::work();
50     return 0;
51 }
不存在ti为0

 

以上是关于Jumping的主要内容,如果未能解决你的问题,请参考以下文章

Super Jumping! Jumping! Jumping! HDU - 1087

hdu 1087 Super Jumping! Jumping! Jumping!

Super Jumping! Jumping! Jumping! HDU - 1087

HDU 1087 [Super Jumping! Jumping! Jumping!]动态规划

HDU 1087 Super Jumping! Jumping! Jumping! (DP+LIS)

Super Jumping! Jumping! Jumping!