[倍增][双向链表] Jzoj P3101 开车旅行

Description

 

 

3


 

 

Sample Input

4
2 3 1 4
3
4
1 3
2 3
3 3
4 3
 

【输入输出样例 2】 
10
4 5 6 1 2 3 7 8 9 10
7
10
1 7
2 7
3 7
4 7
5 7
6 7
7 7
8 7
9 7
10 7
 

Sample Output

1
1 1
2 0
0 0
0 0

【输入输出样例 1 说明】 


          各个城市的海拔高度以及两个城市间的距离如上图所示。
          如果从城市 1 出发,可以到达的城市为 2,3,4,这几个城市与城市 1 的距离分别为 1,1,2, 但是由于城市 3 的海拔高度低于城市 2,所以我们认为城市 3 离城市 1 最近,城市 2 离城市 1 第二近,所以小 A 会走到城市 2。到达城市 2 后,前面可以到达的城市为 3,4,这两个城 市与城市 2 的距离分别为 2,1,所以城市 4 离城市 2 最近,因此小 B 会走到城市 4。到达城 市 4 后,前面已没有可到达的城市,所以旅行结束。
          如果从城市 2 出发,可以到达的城市为 3,4,这两个城市与城市 2 的距离分别为 2,1,由 于城市 3 离城市 2 第二近,所以小 A 会走到城市 3。到达城市 3 后,前面尚未旅行的城市为 4,所以城市 4 离城市 3 最近,但是如果要到达城市 4,则总路程为 2+3=5>3,所以小 B 会 直接在城市 3 结束旅行。
          如果从城市 3 出发,可以到达的城市为 4,由于没有离城市 3 第二近的城市,因此旅行 还未开始就结束了。
          如果从城市 4 出发,没有可以到达的城市,因此旅行还未开始就结束了。 



【输入输出样例 2】 
2
3 2
2 4
2 1
2 4
5 1
5 1
2 1
2 0
0 0
0 0
【输入输出样例 2 说明】 
当 X=7 时,
如果从城市 1 出发,则路线为 1 -> 2 -> 3 -> 8 -> 9,小 A 走的距离为 1+2=3,小 B 走的 距离为 1+1=2。( 在城市 1 时,距离小 A 最近的城市是 2 和 6,但是城市 2 的海拔更高,视 为与城市 1 第二近的城市,所以小 A 最终选择城市 2;走到 9 后,小 A 只有城市 10 可以走, 没有第 2 选择可以选,所以没法做出选择,结束旅行)
如果从城市 2 出发,则路线为 2 -> 6 -> 7 ,小 A 和小 B 走的距离分别为 2,4。
如果从城市 3 出发,则路线为 3 -> 8 -> 9,小 A 和小 B 走的距离分别为 2,1。
如果从城市 4 出发,则路线为 4 -> 6 -> 7,小 A 和小 B 走的距离分别为 2,4。
如果从城市 5 出发,则路线为 5 -> 7 -> 8 ,小 A 和小 B 走的距离分别为 5,1。
如果从城市 6 出发,则路线为 6 -> 8 -> 9,小 A 和小 B 走的距离分别为 5,1。
如果从城市 7 出发,则路线为 7 -> 9 -> 10,小 A 和小 B 走的距离分别为 2,1。
如果从城市 8 出发,则路线为 8 -> 10,小 A 和小 B 走的距离分别为 2,0。 
如果从城市 9 出发,则路线为 9,小 A 和小 B 走的距离分别为 0,0(旅行一开始就结 束了)。
如果从城市 10 出发,则路线为 10,小 A 和小 B 走的距离分别为 0,0。
从城市 2 或者城市 4 出发小 A 行驶的路程总数与小 B 行驶的路程总数的比值都最小, 但是城市 2 的海拔更高,所以输出第一行为 2。 
 

 

题解

  • 显然可以发现,我们可以将每个点的最近和次近预处理出来
  • 对于第一问,直接枚举出发点,暴力跑
  • 对于第二问,就是暴力跑
  • 时间复杂度是O(2N^2+NM),这样的话可以过70%
  • 那么考虑,先把高度从小到大排序的位置记录下来,然后用一个双向链表将他们存起来
  • 那么对于B的选择,就是左边第一个还是右边第一个近,谁近就选谁
  • 那么A的选择,假设A先选了左边第一个,那么A的就要选择左边第二个或者是右边第一个中最近的
  • 假设A先选了右边第一个,那就是在左边第一个和右边第二个中找最近的
  • 那么预处理的话,我们就可以用倍增的思想来做
  • 这样的话,查询也是要用倍增的
  • 最后的时间复杂度是O(N log N+M log N)

代码

 1 #include <cstdio>
 2 #include <cmath>
 3 #include <algorithm>
 4 #define ll long long
 5 #define N 100010
 6 using namespace std;
 7 int n,x0,d1,d2,num=1,Q,x,y,h[N],w1[N],w2[N],d[N],left[N],right[N],f[N][20];
 8 ll dis1[N],dis2[N],g[N][20],k[N][20];
 9 bool cmp(int a,int b){ return h[a]<h[b]; }
10 void pd(int x,int y)
11 {
12     if (!y) return;
13     int r=abs(h[x]-h[y]);
14     if (r<dis1[x]||r==dis1[x]&&h[y]<h[w1[x]]) dis2[x]=dis1[x],w2[x]=w1[x],dis1[x]=r,w1[x]=y;
15     else if (r<dis2[x]||r==dis2[x]&&h[y]<h[w2[x]]) dis2[x]=r,w2[x]=y;
16 }
17 void init()
18 {
19     sort(d+1,d+n+1,cmp),dis1[0]=dis2[0]=10000000000;
20     for (int i=1;i<=n;i++) left[d[i]]=d[i-1],right[d[i]]=d[i+1],dis1[i]=dis2[i]=10000000000;
21     for (int i=1;i<=n;i++)
22     {
23         int x2=left[left[i]],x1=left[i],y2=right[right[i]],y1=right[i];
24         pd(i,x2);
25         if (x1!=x2) pd(i,x1);
26         if (y1!=x1&&y1!=x2) pd(i,y1);
27         if (y2!=y1&&y2!=x1&&y2!=x2) pd(i,y2);
28         right[left[i]]=right[i],left[right[i]]=left[i];
29     }
30     for (int i=1;i<=n;i++) f[i][0]=w1[w2[i]],g[i][0]=dis2[i],k[i][0]=dis1[w2[i]];
31     for (int i=1;i<=log2(n/2);i++) for (int j=1;j<=n;j++) f[j][i]=f[f[j][i-1]][i-1],g[j][i]=g[j][i-1]+g[f[j][i-1]][i-1],k[j][i]=k[j][i-1]+k[f[j][i-1]][i-1];
32 }
33 void get(int x,int dis)
34 {
35     for (int i=(int)(log2(n/2));i>=0;i--)
36         if (f[x][i]&&f[x][i]<=n&&dis>=g[x][i]+k[x][i])
37             d1+=g[x][i],d2+=k[x][i],dis-=g[x][i]+k[x][i],x=f[x][i];
38     if (w2[x]&&w2[x]<=n&&dis>=dis2[x]) d1+=dis2[x];
39 }
40 int main()
41 {
42     scanf("%d",&n);
43     for (int i=1;i<=n;i++) scanf("%d",&h[i]),d[i]=i;
44     init(),scanf("%d",&x0);
45     double ans=10000000000;
46     for (int i=1;i<=n;i++)
47     {
48         d1=d2=0,get(i,x0);
49         double p=d1*1.0/d2;
50         if (p<ans||p==ans&&h[i]>h[num]) num=i,ans=p;
51         else if (!d2&&ans==10000000000&&h[i]>h[num]) num=i;
52     }
53     printf("%d\n",num),scanf("%d",&Q);
54     while (Q--)
55     {
56         d1=d2=0,scanf("%d%d",&x,&y),get(x,y);
57         printf("%d %d\n",d1,d2);
58     }
59 }

 

posted @ 2019-01-19 20:04  BEYang_Z  阅读(181)  评论(0编辑  收藏  举报