排序优化+倍增
其实这道题一开始是一点也没有头绪,知道有高人指点了一下。说并不需要拘束于出发点和路径长度,也就是问题1.2。不过一个是固定路径长度的询问,另一个是给定起点和路径长度的询问。
所以问题一和问题二是可以使用一个函数解决的,而且对于一个城市来说,在不考虑路程的情况下,路线是一定的。
然后我们就可以从遍历图变成枚举终点然后判断路程是否合法。
然后为了加速就可以使用倍增处理
对于每个城市,我们需要找他的最近点和次近点。O(N^2)会超时,这时候我们就需要优化可以考虑双向链表进行优化。
我们先按海拔进行排序,然后将标号为1的点拿出来进行处理,显然,只有在链表中的左右相邻的两个的城市(一个方向)才有可能是满足条件的点
然后再将处理完最近和次近的点在链表中删除(因为路径方向是有序的),这时候标号为2的点就成了标号为1的点,这样就可以了。
每次询问,使用倍增进行摸♂索
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
using std::sort;
using std::abs;
const int maxn=101000;
struct node
{
int x;
int y;
int l,r;
};
node city[maxn];
int pos[maxn];
long long dis[maxn][2];
int to[maxn][2];
int stf[maxn][20];
long long sta[maxn][20];
long long stb[maxn][20];
int n;
bool compare(const node &a,const node &b)
{
return a.y<b.y;
}
int read()
{
int res=0,f=1;char c=getchar();
while(c>'9'||c<'0')
{
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9')
{
res=res*10+c-'0';
c=getchar();
}
return res*f;
}
void make_dis(int i,int j)
{
int a=0x7fffffff,b=0x7fffffff,c=-1,d=-1;
for(int l=city[j].l,k=1;l>0&&k<=2;l=city[l].l,k++)
{
int pas=abs(city[j].y-city[l].y);
if(city[l].x<city[j].x) continue;
if(a>pas||(a==pas&&city[c].y>city[l].y))
{
b=a;d=c;
a=pas;
c=l;
}
else if(b>pas||(b==pas&&city[d].y>city[l].y))
{
b=pas;
d=l;
}
}
for(int r=city[j].r,k=1;r<=n&&k<=2;r=city[r].r,k++)
{
int pas=abs(city[j].y-city[r].y);
if(city[r].x<city[r].x) continue;
if(a>pas||(a==pas&&city[c].y>city[r].y))
{
b=a;d=c;
a=pas;
c=r;
}
else if(b>pas||(b==pas&&city[d].y>city[r].y))
{
b=pas;
d=r;
}
}//不大会写这种东西
city[city[j].l].r=city[j].r;
city[city[j].r].l=city[j].l;
dis[i][0]=(a == 0x7fffffff ? 0 : a);
dis[i][1]=(b == 0x7fffffff ? 0 : b);
to[i][0]= ( c == -1 ? 0 : city[c].x );
to[i][1]= ( d == -1 ? 0 : city[d].x );
}
void make_st()
{
for(int i=1;i<=n;i++)
{
stf[i][0]=to[to[i][1]][0];
sta[i][0]=dis[i][1];
stb[i][0]=dis[to[i][1]][0];
}
for(int i=1;i<=19;i++)
for(int j=1;j<=n;j++)
{
stf[j][i]=stf[stf[j][i-1]][i-1];
sta[j][i]=sta[j][i-1]+sta[stf[j][i-1]][i-1];
stb[j][i]=stb[j][i-1]+stb[stf[j][i-1]][i-1];
}
}
void query(int k,int x,long long &a,long long &b)
{
a=0,b=0;
for(int i=19;i>=0;i--)
{
if(!stf[k][i]) continue;
if(a+b+sta[k][i]+stb[k][i]>x) continue;
a+=sta[k][i];
b+=stb[k][i];
k=stf[k][i];
}
if(a+b+dis[k][1]<=x)
a+=dis[k][1];
return ;
}
int main()
{
n=read();
for(int i=1;i<=n;i++)
{
city[i].x=i;
city[i].y=read();
}
sort(city+1,city+1+n,compare);//按照海拔排序
for(int i=1;i<=n;i++)
{
city[i].l=i-1;
city[i].r=i+1;
pos[city[i].x]=i;//链成链表,记录每个城市在链表中的位置
}
for(int i=1;i<=n;i++)
make_dis(i,pos[i]);
make_st();
int x=read();
long long a1=-0x7fffffff,a2=-0x7fffffff;
long long m1=0,m2=0;
double minn=0x7fffffff;
for(int i=1;i<=n;i++)
{
long long a,b;
query(i,x,a,b);
if(b&&1.0*a/b<minn)
{
a2=i;
minn=1.0*a/b;
a1=0x7fffffff;
}
if(!b&&city[pos[i]].y>a1)
{
a1=city[pos[i]].y;
a2=i;
}
}
printf("%d
",a2);
int m=read(),s;
for(int i=1;i<=m;i++)
{
long long a,b;
s=read();x=read();
query(s,x,a,b);
printf("%lld %lld
",a,b);
}
return 0;
}