NOIP 2012 P1081 开车旅行
倍增
这道题最难的应该是预处理。。。
首先用$set$从后往前预处理出每一个点海拔差绝对值得最大值和次大值
因为当前城市的下标只能变大,对于点$i$,在$set$中二分找出与其值最接近的下标
然后再$set$中将左右各两个下标处理出来,取最大值和次小值
预处理完毕
将每一次小A和小B的开车看为一轮开车
然后用$g[i][j]$表示从第i个点出发经过了$2^{j}$轮开车到达的点
$la[i][j]$表示从第i个点出发经过了$2^{j}$轮开车小A开的路程
$lb[i][j]$表示从第i个点出发经过了$2^{j}$轮开车小B开的路程
然后就是倍增处理
还有要注意,当完整的一轮无法在进行后,小A还有可能再开一轮车,进行判断即可
#include <bits/stdc++.h>
#define ll long long
#define inf 1e9
using namespace std;
const ll MAXN=100100;
ll n,x0,a[MAXN],b[MAXN],g[MAXN][32];
ll h[MAXN],where,ding,m;
ll la[MAXN][32],lb[MAXN][32];
double MIN;
set <pair<ll,ll> > s;
bool cmp(pair<ll,ll> a,pair<ll,ll> b)
{
return (abs(a.first-ding)<abs(b.first-ding) || (abs(a.first-ding)==abs(b.first-ding) && h[a.second]<h[b.second]));
}
int main()
{
scanf("%lld",&n);
for (ll i=1;i<=n;i++)
scanf("%lld",&h[i]);
a[n]=b[n]=-1;//-1表示无法再进行开车
s.insert(make_pair(h[n],n));
b[n-1]=n;a[n-1]=-1;
s.insert(make_pair(h[n-1],n-1));
for (ll i=n-2;i>=1;i--)//预处理
{
bool bl=0;
set <pair<ll,ll> > :: iterator it,be;
vector <pair<ll,ll> > k;
k.clear();
it=s.lower_bound(make_pair(h[i],i));
be=s.begin();
be--;
if (it!=s.end())
{
k.push_back(*it);
it++;
bl=1;
}
if (it!=s.end())
k.push_back(*it);
if (bl)
it--;
it--;
if (it!=be)
{
k.push_back(*it);
it--;
}
if (it!=be)
k.push_back(*it);//处理出左右4个点
ding=h[i];
sort(k.begin(),k.end(),cmp);
b[i]=k[0].second;//取最大
a[i]=k[1].second;//取次大
s.insert(make_pair(h[i],i));
}
for (ll i=1;i<=n;i++)
{
g[i][0]=-1;
if (a[i]!=-1 && b[a[i]]!=-1)
{
la[i][0]=abs(h[i]-h[a[i]]);
lb[i][0]=abs(h[a[i]]-h[b[a[i]]]);
g[i][0]=b[a[i]];//倍增预处理
}
}
for (ll i=1;i<=30;i++)
{
for (ll j=1;j<=n;j++)
{
if (g[j][i-1]!=-1 && g[g[j][i-1]][i-1]!=-1)//保证不会超出范围
{
g[j][i]=g[g[j][i-1]][i-1];
la[j][i]=la[j][i-1]+la[g[j][i-1]][i-1];
lb[j][i]=lb[j][i-1]+lb[g[j][i-1]][i-1];//进行倍增
}
else
g[j][i]=-1;
}
}
scanf("%lld",&x0);
MIN=1.0e18+10;
where=0;
for (ll i=1;i<=n;i++)
{
ll ta,tb,now;
ta=tb=0;
now=i;
for (ll j=30;j>=0;j--)//搜索
{
if (g[now][j]!=-1 && ta+tb+la[now][j]+lb[now][j]<=x0)
{
ta+=la[now][j];
tb+=lb[now][j];
now=g[now][j];
}
}
if (a[now]!=-1 && ta+tb+abs(h[now]-h[a[now]])<=x0)
{
ta+=abs(h[now]-h[a[now]]);
now=a[now];
}
double temp;
if (tb==0)
temp=1.0e18;
else
temp=(double)(1.0*ta)/(1.0*tb);
if (temp<MIN)
{
MIN=temp;
where=i;
}
else
if (temp==MIN)
{
if (h[i]>h[where])
where=i;
}
}
printf("%lld\n",where);
scanf("%lld",&m);
for (ll i=1;i<=m;i++)
{
ll now,x;
scanf("%lld%lld",&now,&x);
ll ta,tb;
ta=tb=0;
for (ll j=30;j>=0;j--)
{
if (g[now][j]!=-1 && ta+tb+la[now][j]+lb[now][j]<=x)
{
ta+=la[now][j];
tb+=lb[now][j];
now=g[now][j];
}
}
if (a[now]!=-1 && ta+tb+abs(h[now]-h[a[now]])<=x)
{
ta+=abs(h[now]-h[a[now]]);
now=a[now];
}
printf("%lld %lld\n",ta,tb);
}
}
NOIP 2012 P1081 开车旅行的更多相关文章
- 【CodeVS 1199】【NOIP 2012】开车旅行
http://codevs.cn/problem/1199/ 主要思想是倍增,对于第一个回答从后往前扫,依次插入平衡树中. 我写的splay,比较繁琐. #include<cmath> # ...
- 洛谷 P1081 开车旅行(70)
P1081 开车旅行 题目描述 小AA 和小BB 决定利用假期外出旅行,他们将想去的城市从 11到 NN 编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 ii的海 ...
- [NOIP2012] 提高组 洛谷P1081 开车旅行
题目描述 小 A 和小 B 决定利用假期外出旅行,他们将想去的城市从 1 到 N 编号,且编号较小的 城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 i 的海拔高度为 Hi,城市 ...
- P1081 开车旅行
题目描述 小 A 和小 B 决定利用假期外出旅行,他们将想去的城市从 1 到 N 编号,且编号较小的 城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 i 的海拔高度为 Hi,城市 ...
- NOIP 2012 洛谷P1081 开车旅行
Description: 就是两个人开车,只能向东开.向东有n个城市,城市之间的距离为他们的高度差.A,B轮流开车,A喜欢到次近的城市,B喜欢到最近的城市.如果车子开到底了或者车子开的路程已经超过了限 ...
- LUOGU P1081 开车旅行 (noip 2012)
传送门 解题思路 这道题刚了一下午,主要就刚在set那里了.先写了一个暴力70分..之后优化预处理,看着大佬神犇们都用的什么双向链表之类的东西,本蒟蒻不会,又懒得手写平衡树,就拿了个set搞了搞,感觉 ...
- noip2012 P1081 开车旅行
小 A 和小 B 决定利用假期外出旅行,他们将想去的城市从 1 到 N 编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 i 的海拔高度为Hi,城市 i 和城市 j ...
- P1081 开车旅行(Not Finish)
https://www.luogu.org/problemnew/show/P1081
- 洛谷 P1081 开车旅行 —— 倍增
题目:https://www.luogu.org/problemnew/show/P1081 真是倍增好题! 预处理:f[i][j] 表示从 i 点开始走 2^j 次 AB (A,B各走一次)到达的点 ...
随机推荐
- 基于COCA词频表的文本词汇分布测试工具v0.1
美国语言协会对美国人日常使用的英语单词做了一份详细的统计,按照日常使用的频率做成了一张表,称为COCA词频表.排名越低的单词使用频率越高,该表可以用来统计词汇量. 如果你的词汇量约为6000,那么这张 ...
- RFC 8684---TCP Extensions for Multipath Operation with Multiple Addresses
https://datatracker.ietf.org/doc/rfc8684/?include_text=1 TCP Extensions for Multipath Operation with ...
- Python--网络爬虫模块requests模块之响应--response
当requests发送请求成功后,requests就会得到返回值,如果服务器响应正常,就会接收到响应数据: Response响应中的属性和方法 常用属性: status_code: 数据类型:int ...
- day38 Pyhton 并发编程
# 网络编程 # arp协议 : # 1.这是一个通过ip找mac地址的协议 # 2.由于有了socket,用户在使用网络的时候,只需要关心对方用户的ip地址就可以了 # 3.如果用户即将和这个ip进 ...
- Elasticsearch修改字段类型 (_reindex)
1.设置索引t2为想要的数据类型 2.将t1 reindex到t2 3.数据reindex完成删除t1 4.设置索引t1为想要的数据类型 5.将t2 reindex到t1 如果 _reindex 超时 ...
- 【C语言学习笔记】C语言函数执行成功时,返回1和返回0,究竟哪个好?
基本上,没有人会将大段的C语言代码全部塞入 main() 函数,更好的做法是按照复用率高,耦合性低的原则,尽可能的将代码拆分不同的功能模块,并封装成函数.C语言代码的组合千变万化,因此函数的功能可能会 ...
- 【博弈论】CF 1215D Ticket Game
题目大意 洛谷链接 给出一个长度为\(n\)的由数字组成的字符串(\(n\)是偶数).但可能有偶数个位上的数字为?. 现在有两个人\(A\)和\(B\),在?的位置上填\(0\)~\(9\)的数,一直 ...
- rabbitmq 延时队列
前言 某个产品 或者订单,有个有效期 过了有效期要取消 方法一 : 写个脚本,用crontab 定时扫描 改变状态 但是最低只能一分钟 ,不适合 方法二 : 用swoole得毫秒定时器,每秒钟去扫描表 ...
- git的一些操作命令
一,如何修改一个commit的注释? root@kubuntu:/data/git/clog# git commit --amend 说明:架构森林是一个专注架构的博客,地址:https://www. ...
- centos8使用timedatectl管理时间
一,centos8中默认使用chronyd来做时间服务 1,查看chronyd服务的状态 [root@blog ~]# systemctl status chronyd ● chronyd.servi ...