洛谷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 ...
随机推荐
- springboot中参数校验
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring- ...
- MD5/SHA1/Hmac_SHA1
1.MD5 #import <CommonCrypto/CommonDigest.h> + (NSString *) md5:(NSString *) input { const char ...
- Haar分类器方法
一.Haar分类器的前世今生 二.人脸检测属于计算机视觉的范畴,早期人们的主要研究方向是人脸识别,即根据人脸来识别人物的身份,后来在复杂背景下的人脸检测需求越来越大,人脸检测也逐渐作为一个单独的研究方 ...
- boost相关函数
1.boost::scoped_ptr是一个比较简单的智能指针,它能保证在离开作用域之后它所管理对象能被自动释放 #include <iostream> #include <boos ...
- c_ 数据结构_图_邻接矩阵
程序主要实现了图的深度遍历和广度遍历. #include <stdio.h> #include <stdlib.h> #include <string.h> #de ...
- 从别人git下载项目下来然后运行
1点击clone or download 2.自由选择 3.拉到你想放的位置,我是放到桌面上的 4. cmd 打开,进入你 的下载到桌面的项目 5. # install dependencies n ...
- CSIC_716_20191101【编程语言、变量、垃圾回收机制】
编程语言分类:机器语言.汇编语言.高级语言. 机器语言:机器能直接识别的程序语言或指令代码(二进制指令),勿需经过翻译,每一操作码在计算机内部都有相应的电路来完成它 汇编语言:比机器语言略高级,用英文 ...
- ubuntu下安装git提示无root权限
apt-get install git 获取git指令 sudo passwd root 重置unix密码 su root 键入密码 参考链接 https://www.cnblogs.com/2she ...
- Odoo Javascript 参考
本文介绍了odoo javascript框架.从代码行的角度来看,这个框架不是一个大的应用程序,但它是非常通用的,因为它基本上是一个将声明性接口描述转换为活动应用程序的机器,能够与数据库中的每个模型和 ...
- JavaScript - window对象相关
1 . window对象常用方法 : 写法 : window.方法() 注意 : window可以省略不写 alert(), confirm(), prompt()是JavaScript提供和用户交互 ...