60分:
裸的暴力,直接搞dfs。注意double。
直接上代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
const int maxn=100005;
const double INF=0x3f3f3f3f;
struct node
{
int d1,d2;
}e,res[maxn];
int h[maxn],vis[maxn],x0,n,cnt=0;
node find(int x,int flag,node tmp)//flag==1:a
{
int m1=INF,v1=0,m2=INF,v2=0;
for(int i=x+1;i<=n;i++)
{
int temp=abs(h[x]-h[i]);
if(temp<m1||(temp==m1&&h[i]<h[v1]))
{m2=m1;v2=v1;v1=i;m1=temp;}
else if(temp<m2||(temp==m2&&h[i]<h[v2]))
{v2=i;m2=temp;}
}
if(flag==1)
{
if(v2==0) return tmp;
tmp.d1+=m2;
if(tmp.d1+tmp.d2>x0) {tmp.d1-=m2;return tmp;}
else return find(v2,2,tmp);
}
if(flag==2)
{
if(v1==0) return tmp;
tmp.d2+=m1;
if(tmp.d1+tmp.d2>x0) {tmp.d2-=m1;return tmp;}
else return find(v1,1,tmp);
}
}
int main()
{
h[0]=INF;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&h[i]);
scanf("%d",&x0);e.d1=e.d2=0;double minv=INF+1;int v=n+1;h[v]=-1;
for(int i=1;i<=n;i++)
{
node x=find(i,1,e);
double ians;
if(x.d2==0) ians=INF;
else ians=(x.d1*1.0)/(x.d2*1.0);
// cout<<x.d1<<" "<<x.d2<<endl;
// cout<<ians<<endl;
if(ians<minv||(ians==minv&&h[i]>h[v]))
{minv=ians;v=i;}
}
printf("%d\n",v);
int m;scanf("%d",&m);
for(int i=1;i<=m;i++)
{
int st;scanf("%d%d",&st,&x0);
node x=find(st,1,e);
printf("%d %d\n",x.d1,x.d2);
}
return 0;
}
因为我是一条有追求的咸鱼,所以我开始研究100分的算法惹
因为我们要找对于每一个点的最近点和次近点。na:最近点。nb:次近点。
这里用链表,不想多说惹。。。
然后我们需要知道a(b)走了多少轮后的距离,同时也要把到达的点记录一下,考虑倍增。
fa[i][j]记得是A走2^j轮之后的距离。(B一样)
f[i][j]记得是从i走2^j个两步之后到达的点
然后就是求询问啦,不想啰嗦惹,就是正常的倍增处理呀(不过要分别弄一下a,b emmm)
搞到a,b下面就很好求了啊,还是那句话!!!注意double呐
没惹。。。代码太丑不想贴。。。