题目:https://www.luogu.org/problemnew/show/P1081

预处理从每个点开始a能走多少、b能走多少。可以像dp一样从后往前推。

但有X的限制。所以该数组可以变成倍增的样子。

预处理第一步的找下一个点可以从后往前弄,在树状数组上二分。然后正常转移即可。

树状数组上的二分有细节:

  找第一个 f 值为需要的值k的,可以if( query( mid )>=k )ans=mid,r=mid-1;也可以if( query(mid)<=k-1 )ans=mid,l=mid+1; ans++;

倍增数组也有细节,大约就是当目的地为0的时候就不要给距离赋值了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
using namespace std;
const int N=1e5+;
const double eps=1e-,INF=2e9+;
int n,m,h[N],tp[N],f[N],ps[N],S;
ll X,dp[N][][],mp[N],s[N],ca,cb;
double tc=INF;
int rdn()
{
int ret=,fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=-;ch=getchar();}
while(ch>=''&&ch<='')(ret*=)+=ch-'',ch=getchar();
return ret*fx;
}
ll rdl()
{
ll ret=,fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=-;ch=getchar();}
while(ch>=''&&ch<='')(ret*=)+=ch-'',ch=getchar();
return ret*fx;
}
void add(int x,int k){for(;x<=m;x+=(x&-x))f[x]+=k;}
int query(int x){int ret=;for(;x;x-=(x&-x))ret+=f[x];return ret;}
void find(int i,int &ps0,int &ps1)
{
ps0=;ps1=;
int k=query(h[i]),l=,r=m,tp0=,tp1=,antp=;
// printf("i=%d k=%d\n",i,k);
if(n-i+>k)
{
while(l<=r)
{
int mid=l+r>>;
if(query(mid)<=k)tp0=mid,l=mid+;
else r=mid-;
}
tp0++;
}
if(k>)
{
l=;r=m;
while(l<=r)
{
int mid=l+r>>;
if(query(mid)>=k-)tp1=mid,r=mid-;
else l=mid+;
}
}
if(!tp0&&tp1)ps0=ps[tp1],antp=tp1;else if(tp0&&!tp1)ps0=ps[tp0],antp=tp0;
else if(tp0&&tp1)
{if(tp[h[i]]-tp[tp1]>tp[tp0]-tp[h[i]])ps0=ps[tp0],antp=tp0;else ps0=ps[tp1],antp=tp1;}
// printf("tp0=%d tp1=%d ps0=%d\n",tp0,tp1,ps0);
if(antp)add(antp,-);
k=query(h[i]);tp0=tp1=;
// printf("i=%d k=%d(antp=%d)\n",i,k,antp);
if(n-i>k)
{
l=;r=m;
while(l<=r)
{
int mid=l+r>>;
if(query(mid)<=k)tp0=mid,l=mid+;
else r=mid-;
}
tp0++;
}
if(k>)
{
l=;r=m;
while(l<=r)
{
int mid=l+r>>;
if(query(mid)>=k-)tp1=mid,r=mid-;
else l=mid+;
}
}
if(!tp0&&tp1)ps1=ps[tp1];else if(tp0&&!tp1)ps1=ps[tp0];
else if(tp0&&tp1){if(tp[h[i]]-tp[tp1]>tp[tp0]-tp[h[i]])ps1=ps[tp0];else ps1=ps[tp1];}
// printf("tp0=%d tp1=%d ps1=%d\n",tp0,tp1,ps1);
if(antp)add(antp,);
}
void cz(int cr)
{
int a,b;find(cr,b,a);
dp[cr][][]=a;mp[cr]=b;
if(a)dp[cr][][]=abs(tp[h[a]]-tp[h[cr]]); int ta=mp[a];
if(ta)
{
dp[cr][][]=ta;
dp[cr][][]=dp[cr][][]; if(ta)dp[cr][][]=abs(tp[h[ta]]-tp[h[a]]);
}
// printf("cr=%d a=%lld b=%lld(a=%d ta=%d)\n",cr,dp[cr][1][0],dp[cr][1][1],a,ta); for(int i=;i<=;i++)
{
a=dp[cr][i-][];if(!dp[a][i-][])break;//
dp[cr][i][]=dp[cr][i-][]+dp[a][i-][];
dp[cr][i][]=dp[cr][i-][]+dp[a][i-][];
dp[cr][i][]=dp[a][i-][];
}
}
int main()
{
n=rdn();
for(int i=;i<=n;i++)tp[i]=h[i]=rdn();
sort(tp+,tp+n+);m=unique(tp+,tp+n+)-tp-;
for(int i=n;i;i--)
{
h[i]=lower_bound(tp+,tp+n+,h[i])-tp;
add(h[i],);ps[h[i]]=i;cz(i);
}
X=rdl();ll yX=X;
for(int i=;i<=n;i++)
{
// printf("i=%d\n",i);
int now=i;ca=;cb=;X=yX;
for(int j=;j;j--)
// {
// if(j<=3)printf("X=%lld now=%d j=%d a=%lld b=%lld\n"
// ,X,now,j,dp[now][j][0],dp[now][j][1]);
if(dp[now][j][]+dp[now][j][]<=X)
{
X-=dp[now][j][]+dp[now][j][];
ca+=dp[now][j][];cb+=dp[now][j][];
if(dp[now][j][])now=dp[now][j][];
}
// }
// printf("X=%lld now=%d j=0 a=%lld\n",X,now,dp[now][0][0]);
if(now&&dp[now][][]<=X)ca+=dp[now][][];
// printf("i=%d ca=%lld cb=%lld\n",i,ca,cb);
if(cb)
{
double w=(double)ca/cb;
if(w<tc||(fabs(w-tc)<=eps&&h[i]>h[S]))tc=w,S=i;
}
// printf("i=%d S=%d\n",i,S);
}
printf("%d\n",S);
m=rdn();
while(m--)
{
S=rdn();X=rdn();
int now=S;ca=;cb=;
for(int j=;j;j--)
// {
// if(j<=3)printf("X=%lld now=%d j=%d a=%lld b=%lld\n"
// ,X,now,j,dp[now][j][0],dp[now][j][1]);
if(dp[now][j][]+dp[now][j][]<=X)
{
X-=dp[now][j][]+dp[now][j][];
ca+=dp[now][j][];cb+=dp[now][j][];
if(dp[now][j][])now=dp[now][j][];
}
// }
// printf("X=%lld now=%d j=0 a=%lld\n",X,now,dp[now][0][0]);
if(now&&dp[now][][]<=X)ca+=dp[now][][];
printf("%lld %lld\n",ca,cb);
}
return ;
}

洛谷1081 (NOIp2012) 开车旅行——倍增预处理的更多相关文章

  1. P1081 [NOIP2012]开车旅行[倍增]

    P1081 开车旅行    题面较为啰嗦.大概概括:一个数列,只能从一个点向后走,两种方案:A.走到和自己差的绝对值次小的点B.走到和自己差的绝对值最小点:花费为此差绝对值:若干询问从规定点向后最多花 ...

  2. Luogu1081 NOIP2012 开车旅行 倍增

    题目传送门 为什么NOIP的题目都这么长qwq 话说2012的D1T3和D2T3都是大火题啊qwq 预处理神题 对于这种跳跳跳的题目考虑使用倍增优化枚举.先预处理某个点之后距离最小和次小的城市,然后倍 ...

  3. Luogu 1081 [NOIP2012] 开车旅行

    感谢$LOJ$的数据让我调掉此题. 这道题的难点真的是预处理啊…… 首先我们预处理出小$A$和小$B$在每一个城市的时候会走向哪一个城市$ga_i$和$gb_i$,我们有链表和平衡树可以解决这个问题( ...

  4. 洛谷P1027 Car的旅行路线

    洛谷P1027 Car的旅行路线 题目描述 又到暑假了,住在城市A的Car想和朋友一起去城市B旅游.她知道每个城市都有四个飞机场,分别位于一个矩形的四个顶点上,同一个城市中两个机场之间有一条笔直的高速 ...

  5. DP【洛谷P2134】 百日旅行

    [洛谷P2134] 百日旅行 题目背景 重要的不是去哪里,而是和你在一起.--小红 对小明和小红来说,2014年7月29日是一个美好的日子.这一天是他们相识100天的纪念日. (小明:小红,感谢你2场 ...

  6. Cogs 1264. [NOIP2012] 开车旅行(70分 暴力)

    1264. [NOIP2012] 开车旅行 ★★☆   输入文件:drive.in   输出文件:drive.out   简单对比时间限制:2 s   内存限制:128 MB [题目描述] 小A 和小 ...

  7. 洛谷 P1081 开车旅行 —— 倍增

    题目:https://www.luogu.org/problemnew/show/P1081 真是倍增好题! 预处理:f[i][j] 表示从 i 点开始走 2^j 次 AB (A,B各走一次)到达的点 ...

  8. noip2012开车旅行 题解

    题目大意: 给出n个排成一行的城市,每个城市有一个不同的海拔.定义两个城市间的距离等于他们的高度差的绝对值,且绝对值相等的时候海拔低的距离近.有两个人轮流开车,从左往右走.A每次都选最近的,B每次都选 ...

  9. 洛谷1736(二维dp+预处理)

    洛谷1387的进阶版,但很像. 1387要求是“全为1的正方形”,取dp[i][j] = min(dp[i-1][j-1], min(dp[i-1][j], dp[i][j-1]))吧?这个有“只有对 ...

随机推荐

  1. Spring MVC(四)--控制器接受pojo参数

    以pojo的方式传递参数适用于参数较多的情况,或者是传递对象的这种情况,比如要创建一个用户,用户有十多个属性,此时就可以通过用户的pojo对象来传参数,需要注意的是前端各字段的名称和pojo对应的属性 ...

  2. 《DSP using MATLAB》Problem 7.38

    代码: %% ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ %% Output In ...

  3. 【51nod 1874】 奇怪的数学题

    题目 求 \[\sum_{i=1}^n\sum_{j=1}^nsgcd(i,j)^k\] 首先这个次大公约数显然就是\(gcd\)除一下最小质因子了 于是 \[\sum_{i=1}^n\sum_{j= ...

  4. 2019-2-18-VisualStudio-给项目添加特殊的-Nuget-的链接

    title author date CreateTime categories VisualStudio 给项目添加特殊的 Nuget 的链接 lindexi 2019-02-18 15:56:48 ...

  5. 牛客NOIP暑期七天营-提高组6

    目录 A-积木大赛 题目描述 link 题解 代码 B-破碎的序列 题目描述 link 题解 C-分班问题 题目描述 link 题解 比赛链接 官方题解 A-积木大赛 题目描述 link 题解 标签: ...

  6. 【核心核心】8.Spring【AOP】注解方式

    1.引入jar包 sprig框架基础包+JUntil整合包+日志包+AOP包 spring的传统AOP的开发的包 spring-aop-4.2.4.RELEASE.jar com.springsour ...

  7. Django--csrf跨站请求伪造、Auth认证模块

    form表单中使用跨站请求伪造 { % csrf_token % } 会动态生成一个input框,内部的value是随机刷新的 如果不想校验csrf from django.views.decorat ...

  8. TZOJ 2965 A Coin Game(DP)

    描述 Farmer John's cows like to play coin games so FJ has invented with a new two-player coin game cal ...

  9. LA3902 Networlk

    Network Consider a tree network with n nodes where the internal nodes correspond to servers and the ...

  10. apk反编译(6)用ProGuard 混淆、压缩代码,压缩资源。

    1.android官方文档 https://developer.android.com/studio/build/shrink-code  主要内容如下: 1.1 压缩代码 混淆生成的文件:<m ...