洛谷P1081——开车旅行
传送门:QAQQAQ
题意注意点:
1.是从前往后走,不能回头
2.小A小B轮流开,先小A开,而小A是到第二近的点(这点调试的时候查了好久)
3.若绝对值差相同海拔低的更近,而第一个询问若比值相同是海拔高的更优
思路:我们先预处理出离i点最近和次近点的编号,没有就是-1(链表可以达到O(n),但是用STL O(nlog(n)) 绰绰有余,代码量还小)
然后用倍增预处理出从i号点走2^j轮A走的路程,B走的路程,和走完这些轮最终停下的点(定义AB各走一次为一轮)
注意可能走半轮,即最后一下A走B不走。
写题过程:
大佬MYY告诉我不要心急,先打70分暴力,然后打了2个小时暴力(STL真的好难查啊QAQ) 打完暴力以后告诉我主程序要全部删掉重写。。。。。
看到直接旁边的HCY没打暴力直接正解AC,心态崩了。。。
然后就在没有特判掉走不到的情况和AB顺序一半写正,一般写反上调了好久,不过最终做出来还是蛮有成就感的(感觉自己很弱啊。。)
代码:
#include<bits/stdc++.h>
#define m_k make_pair
#define ll long long
using namespace std;
const ll N=;
const ll inf=(ll)5e18; ll f[N][],n,m,a[N],x0;
//0:closest 1:second closest
ll dp[N][][],Bits[],p[N][];
//0:disB 1:disA p:finalpos AB为一轮,走2^t轮 ll _abs(ll x)
{
if(x<) return -x;
else return x;
} set<pair<ll,ll> > st;
vector<pair<ll,ll> > tmp;
void init()
{
memset(f,-,sizeof(f));
st.insert(m_k(a[n],n));
st.insert(m_k(a[n-],n-));
f[n-][]=n;
for(ll i=n-;i>=;i--)
{
ll bl=;
tmp.clear();
set<pair<ll,ll> > :: iterator it;
it=st.lower_bound(m_k(a[i],i));
if(it!=st.end()) tmp.push_back(*it),it++,bl++;
if(it!=st.end()) tmp.push_back(*it);
if(bl) it--;
it--;
set<pair<ll,ll> > :: iterator be;
be=st.begin(); be--;
if(it!=be) tmp.push_back(*it),it--;
if(it!=be) tmp.push_back(*it);
ll ans1=inf,ans2=inf;
for(ll j=;j<(ll)tmp.size();j++)
{
if(ans1>_abs(a[i]-tmp[j].first)||(ans1==_abs(a[i]-tmp[j].first)&&a[f[i][]]>tmp[j].first))
{
f[i][]=f[i][]; ans2=ans1;
f[i][]=tmp[j].second; ans1=_abs(a[i]-tmp[j].first);
}
else if(ans2>_abs(a[i]-tmp[j].first)||(ans2==_abs(a[i]-tmp[j].first)&&a[f[i][]]>tmp[j].first))
{
f[i][]=tmp[j].second; ans2=_abs(a[i]-tmp[j].first);
}
}
st.insert(m_k(a[i],i));
}
} void ready()
{
memset(p,-,sizeof(p));
memset(dp,-,sizeof(dp));
for(ll i=;i<=n;i++)
{
ll pos=f[i][]; if(pos==-) continue;
dp[i][][]=_abs(a[pos]-a[i]);
if(f[pos][]==-) continue;
dp[i][][]=_abs(a[pos]-a[f[pos][]]);
p[i][]=f[pos][];
}
for(ll j=;j<;j++)
{
for(ll i=;i<=n;i++)
{
for(ll k=;k<=;k++)
if(dp[i][j-][k]!=-&&dp[p[i][j-]][j-][k]!=-) dp[i][j][k]=dp[i][j-][k]+dp[p[i][j-]][j-][k];
if(p[i][j-]!=-) p[i][j]=p[p[i][j-]][j-]; }
}
} ll suma,sumb;
double calc(ll x,ll y)
{
if(y==) return inf*1.0;
return(x*1.0)/(y*1.0);
} int main()
{
scanf("%lld",&n);
for(ll i=;i<=n;i++) scanf("%lld",&a[i]);
init();
ready();
scanf("%lld",&x0);
double ans=inf*1.0;
ll now=;
a[]=-inf;
for(int i=;i<=n;i++)
{
ll suma=,sumb=,pos=i;
for(int j=;j>=;j--)
{
if(dp[pos][j][]==-||dp[pos][j][]==-||p[pos][j]==-) continue;
if(dp[pos][j][]+dp[pos][j][]+suma+sumb>x0) continue;
suma+=dp[pos][j][];
sumb+=dp[pos][j][];
pos=p[pos][j];
}
if(dp[pos][][]+suma+sumb<=x0&&dp[pos][][]!=-) suma+=dp[pos][][];
if(ans>calc(suma,sumb)||(ans==calc(suma,sumb)&&a[i]>a[now]))
{
now=i;
ans=calc(suma,sumb);
}
}
cout<<now<<endl; ll pos;
scanf("%lld",&m);
for(int i=;i<=m;i++)
{
scanf("%lld%lld",&pos,&x0);
suma=; sumb=;
for(int j=;j>=;j--)
{
if(dp[pos][j][]==-||dp[pos][j][]==-||p[pos][j]==-) continue;
if(dp[pos][j][]+dp[pos][j][]+suma+sumb>x0) continue;
suma+=dp[pos][j][];
sumb+=dp[pos][j][];
pos=p[pos][j];
}
if(dp[pos][][]+suma+sumb<=x0&&dp[pos][][]!=-) suma+=dp[pos][][];
printf("%lld %lld\n",suma,sumb);
}
return ;
}
洛谷P1081——开车旅行的更多相关文章
- 洛谷 P1081 开车旅行(70)
P1081 开车旅行 题目描述 小AA 和小BB 决定利用假期外出旅行,他们将想去的城市从 11到 NN 编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 ii的海 ...
- [NOIP2012] 提高组 洛谷P1081 开车旅行
题目描述 小 A 和小 B 决定利用假期外出旅行,他们将想去的城市从 1 到 N 编号,且编号较小的 城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 i 的海拔高度为 Hi,城市 ...
- NOIP 2012 洛谷P1081 开车旅行
Description: 就是两个人开车,只能向东开.向东有n个城市,城市之间的距离为他们的高度差.A,B轮流开车,A喜欢到次近的城市,B喜欢到最近的城市.如果车子开到底了或者车子开的路程已经超过了限 ...
- 洛谷 P1081 开车旅行 —— 倍增
题目:https://www.luogu.org/problemnew/show/P1081 真是倍增好题! 预处理:f[i][j] 表示从 i 点开始走 2^j 次 AB (A,B各走一次)到达的点 ...
- 2018.11.04 洛谷P1081 开车旅行(倍增)
传送门 思路简单码量超凡? 感觉看完题大家应该都知道是倍增sbsbsb题了吧. 首先预处理出从每个点出发如果是AAA走到哪个点,如果是BBB走到哪个点. 然后利用刚刚预处理出的信息再预处理从每个点出发 ...
- 洛谷P1081 开车旅行(倍增)
题意 题目链接 Sol 咕了一年的题解.. 并不算是很难,只是代码有点毒瘤 \(f[i][j]\)表示从\(i\)号节点出发走了\(2^j\)轮后总的距离 \(da[i][j]\)同理表示\(a\)的 ...
- 洛谷P1081 开车旅行70分
https://www.luogu.org/problem/show?pid=1081 太遗憾了明明写出来了,却把最小值初始值弄小了,从第二个点开始就不可能对了.70分! #include<io ...
- 洛谷 P1081 开车旅行【双向链表+倍增】
倍增数组的20和N写反了反复WAWAWA-- 注意到a和b在每个点上出发都会到一个指定的点,所以这样构成了两棵以n点为根的树 假设我们建出了这两棵树,对于第一问就可以枚举起点然后倍增的找出ab路径长度 ...
- 洛谷P1081 开车旅行
题目 双向链表+倍增+模拟. \(70pts\): 说白了此题的暴力就是细节较多的模拟题. 我们设离\(i\)城市最近的点的位置为\(B[i]\),第二近的位置为\(A[i]\).设\(A\)或\(B ...
随机推荐
- 14-MySQL-Ubuntu-数据表的查询-范围查询(三)
范围查询 1,不连续查询-in, not in 查询年龄是12,18,34的学生姓名和年龄信息 select name,age from students where age in (12,18,34 ...
- CSS Sprites(CSS图像拼合技术)教程、工具集合
本集合是有一位国外设计师收集整合,并由 oncoding翻译成中文的,感谢他们的辛苦贡献.CSS Sprites技术在国外并不是什么新技术,只不过近两年(尤其08年开始)中国开始流行这个词,大家也开始 ...
- PHP算法之按奇偶排序数组
给定一个非负整数数组 A,返回一个数组,在该数组中, A 的所有偶数元素之后跟着所有奇数元素. 你可以返回满足此条件的任何数组作为答案. 示例: 输入:[3,1,2,4]输出:[2,4,3,1]输出 ...
- 关于 wpf 的ICommand 的 CanExecute CanExecuteChanged func action的认识
关于 wpf 的ICommand 的 CanExecute CanExecuteChanged func action的认识
- BIO 详解
调用者主动等待调用的结果 简介 早期的jdk中,采用BIO通信模式: 通常有一个acceptor(消费者) 去负责监听客户端的连接. 它接收到客户端的连接请求之后为每个客户端创建一个线程进行链路处理, ...
- ForkJoin学习笔记
1.Fork/Join框架:(分治算法思想) 在必要的情况下,将一个大任务,进行拆分(fork) 成若干个子任务(拆到不能再拆,这里就是指我们制定的拆分的临界值),再将一个个小任务的结果进行join汇 ...
- 一张图轻松掌握 Flink on YARN 应用启动全流程(上)
Flink 支持 Standalone 独立部署和 YARN.Kubernetes.Mesos 等集群部署模式,其中 YARN 集群部署模式在国内的应用越来越广泛.Flink 社区将推出 Flink ...
- RocketMQ源码分析之RocketMQ事务消息实现原下篇(事务提交或回滚)
摘要: 事务消息提交或回滚的实现原理就是根据commitlogOffset找到消息,如果是提交动作,就恢复原消息的主题与队列,再次存入commitlog文件进而转到消息消费队列,供消费者消费,然后将原 ...
- android gradle 和gradle plugin
android gradle 和gradle plugin 1.安装完AS3.5.2创建完项目一运行,报了如下错误 Error:Could not find com.android.tools.bui ...
- NOI2001 炮兵阵地 洛谷2704
题目描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P&quo ...