题意:
给n个点的海拔h[i](不同点海拔不同) 两点的距离为abs(h[i]-h[j]) 有a、b两人轮流开车(只能往下标大的地方开) a每次会开到里当前点第二近的点 b每次会开到离当前点最近的点(距离相同h小的近) 给定x 如果a或b继续开距离和会大于x就不继续开。
求两个问题
1、给定x=x0求从哪点开始开能使a开的距离:b开的距离最小 不值相同取海拔高的
2、给出m个询问 每个询问给定x1、y1 求从x1开始走且x=y1 a能走的距离和b能走的距离
题解:
不难发现(其实我一开始没发现 看了题解才知道TAT)从固定某点i走到的后若干个点和x没关系
我们可以预处理出从i点走j个点 a、b走的距离 由于数据略大 可以用倍增做 move[i][j] 表示i开始走2^j步 a、b走的距离
由于n比较大 不能n^2直接算离某点最近和第二进的点是谁
可以先把所有的h[i]拿来排序 建立双向链表 显然i点的最近点一定是双向链表中i的前驱或后继 而次近点则还可能是前驱的前驱或后继的后继 每次求完将该点从双向链表中删除 这样就能o(n) 求出最近和次近点了
然后我们就可以倍增轻松求出i开始走 且a、b走的距离<=x a、b分别走了多远了(第二个问题解决)
对于第一个问题 也很简单 直接枚从哪个点开始走算ans就完了
代码:
1 #include <cstdio> 2 #include <algorithm> 3 typedef long long ll; 4 using std::sort; 5 const ll N=100001; 6 struct info{ 7 ll t,ma,mb,bo; 8 info(const ll a=0,const ll b=0,const ll c=0,const ll d=0): 9 t(a),ma(b),mb(c),bo(d){} 10 }move[N][20][2],save; 11 struct inli{ 12 ll t,pr,ne; 13 inli(const ll a=0,const ll b=0,const ll c=0): 14 t(a),pr(b),ne(c){} 15 }line[N]; 16 struct inim{ 17 ll t,s; 18 inim(const ll a=0,const ll b=0): 19 t(a),s(b){} 20 }im[N]; 21 inline bool cmp(inim x,inim y){ return x.t<y.t; } 22 ll h[N],sp[N],n,m,x0,ans; 23 void makeline(){ 24 for (ll i=1;i<=n;i++){ 25 line[i].t=im[i].s; 26 if (i>1) line[i].pr=i-1; 27 if (i<n) line[i].ne=i+1; 28 } 29 } 30 void makeres(ll &res1,ll &res2,ll t,ll a1){ 31 if (!a1) return; 32 if (res1==0 || abs(h[t]-h[a1])<abs(h[t]-h[res1]) || 33 (abs(h[t]-h[a1])==abs(h[t]-h[res1]) && h[a1]<h[res1])) res2=res1,res1=a1; 34 else if (res2==0 || abs(h[t]-h[a1])<abs(h[t]-h[res2]) || 35 (abs(h[t]-h[a1])==abs(h[t]-h[res2]) && h[a1]<h[res2])) res2=a1; 36 } 37 inim getmove(ll t,ll a1,ll a2,ll a3,ll a4){ 38 ll res1=0,res2=0; 39 if (t==99) 40 t=99; 41 makeres(res1,res2,t,line[a1].t); 42 makeres(res1,res2,t,line[a2].t); 43 makeres(res1,res2,t,line[a3].t); 44 makeres(res1,res2,t,line[a4].t); 45 if (!res1) return inim(res2,res1); 46 return inim(res1,res2); 47 } 48 void makemove0(){ 49 for (ll i=1;i<n;i++){ 50 if (i==2) 51 i=2; 52 inim x=getmove(i,line[sp[i]].pr,line[sp[i]].pr ? line[line[sp[i]].pr].pr : 0, 53 line[sp[i]].ne,line[sp[i]].ne ? line[line[sp[i]].ne].ne : 0); 54 move[i][0][0].t=x.t; 55 move[i][0][0].ma=abs(h[i]-h[x.t]); 56 move[i][0][0].bo=1; 57 if (x.s){ 58 move[i][0][1].t=x.s; 59 move[i][0][1].mb=abs(h[i]-h[x.s]); 60 move[i][0][1].bo=0; 61 } 62 line[line[sp[i]].pr].ne=line[sp[i]].ne; 63 line[line[sp[i]].ne].pr=line[sp[i]].pr; 64 } 65 } 66 void makemove(){ 67 makemove0(); 68 for (ll i=n;i;i--) 69 for (ll k=0;k<=1;k++){ 70 if (i==1) 71 i=1; 72 for (ll j=1;move[move[i][j-1][k].t][j-1][move[i][j-1][k].bo].t;j++){ 73 info x=move[move[i][j-1][k].t][j-1][move[i][j-1][k].bo]; 74 move[i][j][k].t=x.t; 75 move[i][j][k].bo=x.bo; 76 move[i][j][k].ma=move[i][j-1][k].ma+x.ma; 77 move[i][j][k].mb=move[i][j-1][k].mb+x.mb; 78 } 79 } 80 } 81 info getans(ll x,ll y){ 82 info res=info(x,0,0,1); 83 for (;y>=move[res.t][0][res.bo].ma+move[res.t][0][res.bo].mb && move[res.t][0][res.bo].t;){ 84 ll i=0,st=res.t,sb=res.bo; 85 while (y>=move[st][i][sb].ma+move[st][i][sb].mb && move[st][i][sb].t) ++i; 86 --i; 87 y-=move[st][i][sb].ma+move[st][i][sb].mb; 88 res.t=move[st][i][sb].t; 89 res.bo=move[st][i][sb].bo; 90 res.ma+=move[st][i][sb].ma; 91 res.mb+=move[st][i][sb].mb; 92 } 93 return res; 94 } 95 bool check(info x,ll y){ 96 if (!ans) return 1; 97 if (!x.ma){ 98 if (save.ma) return 0; 99 else return (h[y]>h[ans]); 100 } 101 if (!save.mb) return 1; 102 if (save.ma*x.mb<save.mb*x.ma || (save.ma*x.mb==save.mb*x.ma && h[y]>h[ans])) return 1; 103 else return 0; 104 } 105 int main(){ 106 freopen("drive.in","r",stdin); 107 freopen("drive.out","w",stdout); 108 scanf("%I64d",&n); 109 for (ll i=1;i<=n;i++){ 110 scanf("%I64d",&h[i]); 111 im[i]=inim(h[i],i); 112 } 113 sort(im+1,im+n+1,cmp); 114 for (ll i=1;i<=n;i++) sp[im[i].s]=i; 115 makeline(); 116 makemove(); 117 scanf("%I64d",&x0); 118 for (ll i=1;i<=n;i++){ 119 info x=getans(i,x0); 120 if (check(x,i)) save=x,ans=i; 121 } 122 printf("%I64d\n",ans); 123 scanf("%I64d",&m); 124 ll x,y; 125 for (ll i=1;i<=m;i++){ 126 if (i==54) 127 i=54; 128 scanf("%I64d%I64d",&x,&y); 129 info xx=getans(x,y); 130 printf("%I64d %I64d\n",xx.mb,xx.ma); 131 } 132 fclose(stdin); 133 fclose(stdout); 134 }