题目: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. Struts2中param的作用

    1.页面传参与配置传参的区别:如果页面Form表单的参数在Action类中有相应的setter方法,则会优先取页面Form表单传过来的值,如果页面没有该属性同名的参数,则会从配置文件中取同名的参数值作 ...

  2. Ajax之json返回结果是集合的处理

    Jquery实现ajax: $.ajax({       type    //数据的提交方式:get和post        url   //数据的提交路径        async   //是否支持 ...

  3. css设置字体小于12px

    p { white-space: nowrap; font-size: .12rem; -webkit-transform-origin-x: 0; //缩小后文字居左 -webkit-transfo ...

  4. highchart接收后台数据用法

    最近做数据分析的时候使用了highchart这个插件,从后台中接收数据的时候出了一些问题,记录下来免得以后忘了. $(function () { var list = {$weeklist}; var ...

  5. OSG实现利用菲波那契网格(Fibonacci lattice 或 Fibonacci grid)均分球面

    #include<Windows.h> #include<osg/Node> #include<osg/Geode> #include<osg/Group&g ...

  6. 枚举进程,线程,堆 CreateToolhelp32Snapshot

    Takes a snapshot of the processes and the heaps, modules, and threads used by the processes.对当前系统进行一 ...

  7. 【2019云栖大会】这一场,我们好好聊聊5G和边缘计算

    一年一度的科技盛会杭州云栖大会Apsara Conference就要来了9月25-27日数万名开发者将齐聚杭州云栖小镇共同探索人类科技演进的脉搏聚焦面向未来的创新.热点技术话题 5G和边缘计算是201 ...

  8. C语言作用域、链接属性和存储类型

    C/C++中作用域详解 作用域 编译器可以确认的4种作用域-代码块作用域.文件作用域.函数作用域和原型作用域,一般来说,标识符(包括变量名和函数名)声明的位置决定它的作用域. (1)代码块作用域 一对 ...

  9. xshell上传文件到linux

    z,sz是Linux/Unix同Windows进行ZModem文件传输的命令行工具. 优点就是不用再开一个sftp工具登录上去上传下载文件. sz:将选定的文件发送(send)到本地机器 rz:运行该 ...

  10. pyd打包补充

    网上说的将python代码,通过Cython打包成pyd的教程挺多,好处也多,主要有两个: 1.隐藏代码 2.加速运行速度 补充两点: 1.打包脚本配置 __build__.py from distu ...