【NOIP2012提高组】开车旅行
这题倍增。
当拿到a数组时,我们便记录他的位置并排个序(再用一个数组)
然后,我们就将其变成一个链表的样子。
由于题目要求每次这能从左边走到右边,
所以我们便从1开始枚举到n,
设nx[i][j]表示从i走2j步所到达的点
f[i][j][0/1]表示到达A/B所走的路程
(一步表示A一天+B一天)
PS:luogu的也A了
上标:
#include<cstdio>
#include<algorithm>
#define ll long long
#define N 100010
using namespace std;
ll nx[N][19],f[N][19][2],cl[N][2];
int n,X,m,a[N],b[N],c[N],l[N],r[N],s,x;
ll A,B,fr=0,mA=(1<<30),mB=1;
inline int read()
{
int x=0,f=0; char c=getchar();
while (c<'0' || c>'9') f=(c=='-') ? 1:f,c=getchar();
while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return f ? -x:x;
}
void qsort(int l,int r)
{
int i=l,j=r,mid=c[l+r>>1],mid1=b[l+r>>1];
while (i<j)
{
while (c[i]<mid || (c[i]==mid && b[i]<mid1)) i++;
while (c[j]>mid || (c[j]==mid && b[j]>mid1)) j--;
if (i<=j)
{
swap(c[i],c[j]);
swap(b[i],b[j]);
i++,j--;
}
}
if (i<r) qsort(i,r);
if (l<j) qsort(l,j);
}
void jump(int x,int s)
{
A=0,B=0;
for (int i=16;i>=0;i--)
while (nx[x][i] && A+B+f[x][i][0]+f[x][i][1]<=s)
A+=f[x][i][0],B+=f[x][i][1],x=nx[x][i];
if (cl[x][1] && A+B+abs(a[cl[x][1]]-a[x])<=s) A+=abs(a[cl[x][1]]-a[x]);
}
int main()
{
freopen("drive.in","r",stdin);
freopen("drive.out","w",stdout);
n=read();
for (int i=1;i<=n;i++) c[i]=a[i]=read(),b[i]=i;
qsort(1,n);
for (int i=1;i<=n;i++) l[b[i]]=b[i-1],r[b[i]]=b[i+1];
for (int i=1;i<=n;i++)
{
if (!l[i] && !r[i]) continue;
if (!l[i]) cl[i][0]=r[i],cl[i][1]=r[r[i]],l[r[i]]=0;
else if (!r[i]) cl[i][0]=l[i],cl[i][1]=l[l[i]],r[l[i]]=0;
else
{
if (abs(a[i]-a[l[i]])==abs(a[i]-a[r[i]]))
{
if (a[l[i]]<a[r[i]])
{
cl[i][0]=l[i],cl[i][1]=r[i];
r[l[i]]=r[i],l[r[i]]=l[i];
}
else
{
cl[i][0]=r[i],cl[i][1]=l[i];
r[l[i]]=r[i],l[r[i]]=l[i];
}
}
else if (abs(a[i]-a[l[i]])<abs(a[i]-a[r[i]]))
{
cl[i][0]=l[i];
if (!l[l[i]]) cl[i][1]=r[i];
else if (abs(a[i]-a[l[l[i]]])==abs(a[i]-a[r[i]]) && a[l[l[i]]]<a[r[i]]) cl[i][1]=l[l[i]];
else if (abs(a[i]-a[l[l[i]]])<abs(a[i]-a[r[i]])) cl[i][1]=l[l[i]];
else cl[i][1]=r[i];
r[l[i]]=r[i],l[r[i]]=l[i];
}
else
{
cl[i][0]=r[i];
if (!r[r[i]]) cl[i][1]=l[i];
else if (abs(a[i]-a[r[r[i]]])==abs(a[i]-a[l[i]]) && a[r[r[i]]]<a[l[i]]) cl[i][1]=r[r[i]];
else if (abs(a[i]-a[r[r[i]]])<abs(a[i]-a[l[i]])) cl[i][1]=r[r[i]];
else cl[i][1]=l[i];
r[l[i]]=r[i],l[r[i]]=l[i];
}
}
}
for (int i=1;i<=n;i++)
{
nx[i][0]=cl[cl[i][1]][0];
if (cl[i][1])
{
f[i][0][0]=abs(a[cl[i][1]]-a[i]);
if (nx[i][0])
f[i][0][1]=abs(a[nx[i][0]]-a[cl[i][1]]);
}
}
for (int j=1;j<=16;j++)
for (int i=1;i<=n;i++)
{
nx[i][j]=nx[nx[i][j-1]][j-1];
f[i][j][0]=f[i][j-1][0]+f[nx[i][j-1]][j-1][0];
f[i][j][1]=f[i][j-1][1]+f[nx[i][j-1]][j-1][1];
}
X=read();
for (int i=1;i<=n;i++)
{
jump(i,X);
if (!B) continue;
if ((double)mA/mB>(double)A/B)
mA=A,mB=B,fr=i;
}
printf("%d\n",fr);
m=read();
for (int i=1;i<=m;i++)
{
s=read(),x=read(),jump(s,x);
printf("%lld %lld\n",A,B);
}
return 0;
}
转载需注明出处。