题意:小
旅行过程中,小
小
在启程之前,小
1、 对于一个给定的
2、对任意给定的
这道题居然是倍增。。
我们将城市沿海拔高度排序,因此离城市
我们按编号从小到大枚举城市,用
接着由于
同理,我们采取
接着考虑转移,只有当
for(int i=1;i<=18;i++)
for(int j=1;j<=n;j++)
for(int k=0;k<=1;k++)
{
int l=0;
if(i==1)
l=k^1;
else
l=k;
if(f[i-1][j][k])
f[i][j][k]=f[i-1][f[i-1][j][k]][l];
if(f[i][j][k])
{
disa[i][j][k]=disa[i-1][j][k]+disa[i-1][f[i-1][j][k]][l];
disb[i][j][k]=disb[i-1][j][k]+disb[i-1][f[i-1][j][k]][l];
}
}
接着处理两个询问的共同问题,即从某个城市 solve。
我们选择将
void solve(int s,long long x)
{
da=db=0;
int k=0;
for(int i=18;i>=0;i--)
if(f[i][s][k]&&disa[i][s][k]+disb[i][s][k]<=x)
{
x-=(disa[i][s][k]+disb[i][s][k]);
da+=disa[i][s][k];
db+=disb[i][s][k];
if(!i)
k^=1;
s=f[i][s][k];
}
}
最后对于第 solve 操作即可。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<ctime>
#define INF 1e9
using namespace std;
const int maxn=100010;
const double Pi=acos(-1.0);
template<class T>void read(T &x)
{
x=0;int f=0;char ch=getchar();
while(ch<'0'||ch>'9') {f|=(ch=='-');ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
x=f?-x:x;
return;
}
int n,m;
int pos[maxn],nexa[maxn],nexb[maxn];
long long f[21][maxn][2],disa[31][maxn][2],disb[31][maxn][2];
long long x0,ansa=1,ansb,s,da,db;
struct city
{
int h;
int id;
int pre;
int sub;
}e[maxn];
int cmp(city a,city b)
{
return a.h<b.h;
}
int check(int a,int b,int x)
{
if(!a)
return e[b].id;
if(!b)
return e[a].id;
if(e[x].h-e[a].h<=e[b].h-e[x].h)
return e[a].id;
else
return e[b].id;
}
void remove(int x)
{
if(e[x].sub)
e[e[x].sub].pre=e[x].pre;
if(e[x].pre)
e[e[x].pre].sub=e[x].sub;
}
void solve(int s,long long x)
{
da=db=0;
int k=0;
for(int i=18;i>=0;i--)
if(f[i][s][k]&&disa[i][s][k]+disb[i][s][k]<=x)
{
x-=(disa[i][s][k]+disb[i][s][k]);
da+=disa[i][s][k];
db+=disb[i][s][k];
if(!i)
k^=1;
s=f[i][s][k];
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&e[i].h);
e[i].id=i;
}
sort(e+1,e+n+1,cmp);
for(int i=1;i<=n;i++)
{
pos[e[i].id]=i;
e[i].pre=i-1;
e[i].sub=i+1;
}
e[1].pre=e[n].sub=0;
for(int i=1;i<n;i++)
{
int x=pos[i];
int l=e[x].pre;
int r=e[x].sub;
if(l&&(e[x].h-e[l].h<=e[r].h-e[x].h||!r))
{
nexb[i]=e[l].id;
nexa[i]=check(e[l].pre,r,x);
}
else
{
nexb[i]=e[r].id;
nexa[i]=check(l,e[r].sub,x);
}
remove(x);
}
for(int i=1;i<=n;i++)
{
if(nexa[i])
{
f[0][i][0]=nexa[i];
disa[0][i][0]=abs(e[pos[i]].h-e[pos[nexa[i]]].h);
disb[0][i][0]=0;
}
if(nexb[i])
{
f[0][i][1]=nexb[i];
disb[0][i][1]=abs(e[pos[i]].h-e[pos[nexb[i]]].h);
disa[0][i][1]=0;
}
}
for(int i=1;i<=18;i++)
for(int j=1;j<=n;j++)
for(int k=0;k<=1;k++)
{
int l=0;
if(i==1)
l=k^1;
else
l=k;
if(f[i-1][j][k])
f[i][j][k]=f[i-1][f[i-1][j][k]][l];
if(f[i][j][k])
{
disa[i][j][k]=disa[i-1][j][k]+disa[i-1][f[i-1][j][k]][l];
disb[i][j][k]=disb[i-1][j][k]+disb[i-1][f[i-1][j][k]][l];
}
}
scanf("%lld",&x0);
for(int i=1;i<=n;i++)
{
solve(i,x0);
if(!db)
da=1;
if(da*ansb<db*ansa||(da*ansb==db*ansa&&e[pos[i]].h>e[pos[s]].h))
{
ansa=da;
ansb=db;
s=i;
}
}
printf("%lld\n",s);
scanf("%d",&m);
while(m--)
{
scanf("%lld%lld",&s,&x0);
solve(s,x0);
printf("%lld %lld\n",da,db);
}
return 0;
}