正题
题目大意:https://www.luogu.org/problemnew/show/P1081
题目大意
有若干个城市有不同的海拔hhh,两个城市之间的距离定义为∣hx−hy∣|h_x-h_y|∣hx−hy∣
小A每次走次近的,小B每次走最近的。它们轮流开车。且只会往编号更大的城市开。
问一:在距离≤X\leq X≤X的情况下求一个起点是的他们两个开的距离之和最小。
问二:若干个Si,XiS_i,X_iSi,Xi求在SiS_iSi出发,距离≤Xi\leq X_i≤Xi时他们各开多远。
解题思路
首先链表(或平衡树)预处理出gaiga_igai和gbigb_igbi表示在第iii个城市小AAA或小BBB下一个会到的城市。
然后考虑dpdpdp
设fi,j,0/1f_{i,j,0/1}fi,j,0/1表示从jjj出发走了2i2^i2i次,到小A/小B开车,到达的地点。
设dai,j,0/1da_{i,j,0/1}dai,j,0/1表示从jjj出发走了2i2^i2i次,到小A/小B开车,小AAA走了多远。
设dbi,j,0/1db_{i,j,0/1}dbi,j,0/1表示从jjj出发走了2i2^i2i次,到小A/小B开车,小BBB走了多远。
然后首先
f0,j,0=gaj,f0,j,1=gbjf_{0,j,0}=ga_j,f_{0,j,1}=gb_jf0,j,0=gaj,f0,j,1=gbj
da0,j,0=dist(j,gaj),da0,j,1=0da_{0,j,0}=dist(j,ga_{j}),da_{0,j,1}=0da0,j,0=dist(j,gaj),da0,j,1=0
db0,j,1=dist(j,gbj),db0,j,0=0db_{0,j,1}=dist(j,gb_{j}),db_{0,j,0}=0db0,j,1=dist(j,gbj),db0,j,0=0
然后考虑转移
当i=1i=1i=1时
fi,j,k=fi−1,fi−1,j,k,kxor1f_{i,j,k}=f_{i-1,f_{i-1,j,k},k\ xor\ 1}fi,j,k=fi−1,fi−1,j,k,k xor 1
dai,j,k=dai−1,j,k+dai−1,fi−1,j,k,kxor1da_{i,j,k}=da_{i-1,j,k}+da_{i-1,f_{i-1,j,k},k\ xor\ 1}dai,j,k=dai−1,j,k+dai−1,fi−1,j,k,k xor 1
dbi,j,k=dbi−1,j,k+dbi−1,fi−1,j,k,kxor1db_{i,j,k}=db_{i-1,j,k}+db_{i-1,f_{i-1,j,k},k\ xor\ 1}dbi,j,k=dbi−1,j,k+dbi−1,fi−1,j,k,k xor 1
但是因为i>1i>1i>1时2i2^i2i依旧是偶数,说以kkk不需要改变
fi,j,k=fi−1,fi−1,j,k,kf_{i,j,k}=f_{i-1,f_{i-1,j,k},k}fi,j,k=fi−1,fi−1,j,k,k
dai,j,k=dai−1,j,k+dai−1,fi−1,j,k,kda_{i,j,k}=da_{i-1,j,k}+da_{i-1,f_{i-1,j,k},k}dai,j,k=dai−1,j,k+dai−1,fi−1,j,k,k
dbi,j,k=dbi−1,j,k+dbi−1,fi−1,j,k,kdb_{i,j,k}=db_{i-1,j,k}+db_{i-1,f_{i-1,j,k},k}dbi,j,k=dbi−1,j,k+dbi−1,fi−1,j,k,k
处理好之后,我们定义函数calc(s,x)calc(s,x)calc(s,x)表示
从sss出发,且距离不超过xxx时小AAA和小BBB的行驶距离。
首先我们要设定now,la,lbnow,la,lbnow,la,lb表示现在在哪个点和小AAA和小BBB的行驶距离。
然后当la+lb+dai,now,0+dbi,now,0≤xla+lb+da_{i,now,0}+db_{i,now,0}\leq xla+lb+dai,now,0+dbi,now,0≤x时就证明可以行走,那就对应修改now,la,lbnow,la,lbnow,la,lb的值。
codecodecode
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<set>
#define ll long long
using namespace std;
const ll N=101000;
struct Node{ll h,id,prev,next;
}l[N];
set<int> BST;
double ans;
ll n,m,mark,la,lb,t;
ll h[N],f[21][N][2],da[21][N][2];
ll ga[N],gb[N],db[21][N][2],pre[N];
bool left(ll x){if(!l[x].prev) return 0;if(!l[x].next) return 1;return l[x].h-l[l[x].prev].h<=l[l[x].next].h-l[x].h;
}
ll cmps(ll a,ll b,ll x){if(!a) return l[b].id;if(!b) return l[a].id;if(l[x].h-l[a].h<=l[b].h-l[x].h) return l[a].id;return l[b].id;
}
bool cmp(Node x,Node y)
{return x.h<y.h;}
void Part1()
{for(ll i=1;i<=n;i++)l[i].h=h[i],l[i].id=i;sort(l+1,l+1+n,cmp);for(ll i=1;i<=n;i++)pre[l[i].id]=i;for(ll i=1;i<=n;i++)l[i].prev=i-1,l[i].next=i+1;l[1].prev=l[n].next=0;for(ll i=1;i<=n;i++){ll j=pre[i];if(left(j)) gb[i]=l[l[j].prev].id,ga[i]=cmps(l[l[j].prev].prev,l[j].next,j);else gb[i]=l[l[j].next].id,ga[i]=cmps(l[j].prev,l[l[j].next].next,j);l[l[j].prev].next=l[j].next;l[l[j].next].prev=l[j].prev; }
}
ll dist(ll x,ll y)
{return abs(h[x]-h[y]);}
void Part2()
{for(ll j=1;j<=n;j++){if(ga[j]){f[0][j][0]=ga[j];da[0][j][0]=dist(j,ga[j]);db[0][j][0]=0;}if(gb[j]){f[0][j][1]=gb[j];da[0][j][1]=0;db[0][j][1]=dist(j,gb[j]);}}ll L=0;for(ll i=1;i<=t;i++)for(ll j=1;j<=n;j++)for(ll k=0;k<2;k++){if(i==1) L=k^1;else L=k;f[i][j][k]=f[i-1][f[i-1][j][k]][L];da[i][j][k]=da[i-1][j][k]+da[i-1][f[i-1][j][k]][L];db[i][j][k]=db[i-1][j][k]+db[i-1][f[i-1][j][k]][L];}
}
void calc(ll s,ll x)
{ll now=s;la=lb=0;for(ll i=t;i>=0;i--){if(f[i][now][0]&&la+lb+da[i][now][0]+db[i][now][0]<=x){la+=da[i][now][0];lb+=db[i][now][0];now=f[i][now][0];if(!now) break;}}
}
int main()
{scanf("%lld",&n);t=(int)(log(n*1.0)/log(2.0)+0.001);for(ll i=1;i<=n;i++)scanf("%lld",&h[i]);Part1();Part2();ll X;scanf("%lld",&X);ans=2147483647;for(ll i=1;i<=n;i++){calc(i,X);if(lb&&((double)la/lb)<ans) ans=(double)la/lb,mark=i;}printf("%lld\n",mark);scanf("%lld",&m);for(ll i=1;i<=m;i++){ll s;scanf("%lld%lld",&s,&X);calc(s,X);printf("%lld %lld\n",la,lb);}
}