GDOI2014模拟pty爬山(mountain)

Posted

tags:

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

pty爬山(mountain)

在Pty学校附近,有一座名之为岳之麓的高山。Pty很喜欢和(哔——)一起爬山。
山的平面模型如下:
山由一个顶点集:A1,A2…An给定,保证Ai的x单调递增。我们将Ai和Ai+1之间连上线段,表示山的某一段。如下图所示:
技术分享
Pty想要爬到这座山的最高的顶点,当两个顶点的高度相同时,我们认为x比较大的顶点要高一些。Pty不是盲人,所以他将会在爬山时采取一些策略,使得他能够尽量快的到达最高的顶点。
Pty从初始的顶点出发,往左右看去,他将朝他能够看到的最高的顶点方向走去。当走到每一个顶点时,他都会重新观察,如果这时看到的顶点比之前看到的顶点还要高,那么他将选择此时看到的顶点走去,直到他到达最高点为止。如果顶点A能够看到顶点B,则线段AB没有严格穿过山的内部。
例如上图中:Pty从A4点出发。他能够看到的最高点是A6,所以他将会向右侧走去。当他到达A5号点时,能够看到A1点比A6点更高,所以他会调转方向,向左侧走去。由于A1是最高的顶点,所以他将一直往左侧走,直到到达A1为止。
Pty想知道从每一个顶点出发,分别需要走过多少段才能到达最高点。例如上图中从A4出发需要走过5段才能到达最高点。

输入格式:

第一行输入n,表示n个顶点。
接下来n行,每行两个整数xi, yi,表示第i个顶点的坐标。
输入保证xi单调递增。

输出格式:

输出共n行:第i行表示从第i个顶点出发走到最高点需要经过多少段。

样例输入:

5
1 5
2 4
3 9
4 0
5 2

样例输出:

2
1
0
1
2

数据范围:

30%的数据满足:n<= 100
60%的数据满足:n <= 50000
100%的数据满足:n<=200000, xi<=10^6, yi <= 10^6
i一定能看见i?1
i如果看不见l[i?1],那么一定看不见1~l[i?1]
i如果看得见l[i?1]且看不见l[l[i?1]],那么l[i]=l[i?1]
所以可以用动态规划在O(n)内求出i点向左、向右能看到的最高点。
然后再处理出每个点出发时能看到的最高点,将它按照y与x从小到大排序
按照排序后的顺序,高度从低到高的点依次做。这个点该往哪边走,双向链表中对应方向上与之相邻的点就是要找的点,然后把做过的点删掉即可。(妙!
发现形成了一棵以最高点为根的树,dfs求出答案即可。
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 using namespace std;
 6 const int N=200010;
 7 struct node{
 8     int next,to;
 9 }edge[N];
10 struct no{
11     int y,z,to;
12 }a[N];
13 int n,l[N],r[N],x[N],y[N],head[N],s=0,L[N],R[N],f[N];
14 inline void del(int x)
15 {
16     R[L[x]]=R[x];
17     L[R[x]]=L[x];
18 }
19 inline bool see(int a,int b,int c)//a>b>c
20 {
21     double s=(0.0+y[a]-y[c])/(x[a]-x[c]+0.0);
22     s=s*(x[b]-x[c])+y[c];
23     if(y[b]<=s) return true;
24     else return false;
25 }
26 inline void unite(int x,int y)
27 {
28     s++;
29     edge[s].to=y;
30     edge[s].next=head[x];
31     head[x]=s;
32 }
33 inline void dfs(int x,int dis)
34 {
35     f[x]=dis;
36     for(int i=head[x];i;i=edge[i].next) dfs(edge[i].to,dis+abs(x-edge[i].to));
37 }
38 inline int abs(int x){return (x>0?x:-x);}
39 inline bool cmp(no a,no b){if(a.y!=b.y) return a.y<b.y;return a.to<b.to;}
40 int main()
41 {
42     int mx=-10000000,rec,p,et;
43     scanf("%d",&n);
44     for(int i=1;i<=n;i++)
45     {
46         scanf("%d%d",&x[i],&y[i]);
47         if(mx<=y[i]){mx=y[i];rec=i;}
48     }
49     for(int i=2;i<=n;i++)
50     {
51         l[i]=i-1;
52         while(y[l[i]]<=y[l[l[i]]]&&see(l[l[i]],l[i],i)&&l[i]!=1) l[i]=l[l[i]];
53     }
54     r[n]=n+1;
55     for(int i=n-1;i>=1;i--)
56     {
57         r[i]=i+1;
58         while(y[r[i]]<=y[r[r[i]]]&&see(r[r[i]],r[i],i)&&r[i]!=n) r[i]=r[r[i]];
59     }
60     for(int i=1;i<=n;i++)
61     {
62         R[i]=i+1;
63         L[i]=i-1;
64         a[i].z=i;
65         if(y[r[i]]>=y[l[i]]) a[i].to=r[i];
66         else a[i].to=l[i];
67         a[i].y=y[a[i].to];
68     }
69     a[rec].y=2000000000;
70     sort(a+1,a+n+1,cmp);
71     for(int i=1;i<n;i++)
72     {
73         p=a[i].z;
74         if(a[i].to<p) et=L[p];
75         else et=R[p];
76         unite(et,p);
77         del(p);
78     }
79     dfs(rec,0);
80     for(int i=1;i<=n;i++) printf("%d\n",f[i]);
81     return 0;
82 }

 

 
 











以上是关于GDOI2014模拟pty爬山(mountain)的主要内容,如果未能解决你的问题,请参考以下文章

P1561 [USACO12JAN]爬山Mountain Climbing

洛谷—— P1561 [USACO12JAN]爬山Mountain Climbing

洛谷 P1561 [USACO12JAN]爬山Mountain Climbing

GDOI2014模拟雨天的尾巴

bzoj3874 [ AHOI2014 ] -- 爬山算法

6442. GDOI2020模拟01.18钩子