洛谷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 ...
随机推荐
- 最接近神的人_NOI导刊2010提高(02)
题目描述 破解了符文之语,小FF开启了通往地下的道路.当他走到最底层时,发现正前方有一扇巨石门,门上雕刻着一幅古代人进行某种活动的图案.而石门上方用古代文写着“神的殿堂”.小FF猜想里面应该就有王室的 ...
- Java迷宫代码,深度优先遍历
此次迷宫深度优先遍历寻找路径采用栈结构,每个节点都有固定的行走方向(右下左上),除非一个方向走不通,不然会一条道走到黑. 如果路径存在,打印出行走路径,否则打印出迷宫不存在有效路径. 方向常量定义: ...
- scala中类的简单使用记录
import scala.collection.mutable.ArrayBuffer /** * scala 中内部类的使用 */ class Classes { class Stu(name:St ...
- mySql搜索引擎
转载自 深入浅出mysql数据库 MySQL5.5以后默认使用InnoDB存储引擎,其中InnoDB和BDB提供事务安全表,其它存储引擎都是非事务安全表. 若要修改默认引擎,可以修改配置文件中的def ...
- day34 反射、面向对象内置方法:如__str__、面向对象的软件开发
Python之路,Day21 = 反射.面向对象内置方法:如__str__.面向对象的软件开发 几个内置查看的方法使用 .__base__ 查看类的继承结构.mro() 对象找属性的顺序存在里面 -- ...
- for in循环介绍以及陷阱
大家都知道在JavaScript中提供了两种方式迭代对象: (1)for 循环: (2)for..in循环: 使用for循环进行迭代数组对象,想必大家都已经司空见惯了.但是,使用for.. in循环时 ...
- golang中time包的使用
一.代码 package main; import ( "time" "fmt" ) func main() { //time.Time代表一个纳秒精度的时间点 ...
- arcmap分类标注问题
在给图层标注的时候,经常出现冲突后有些标注出不来,需要将某些个别的点要素进行标注位置调整,如下图: 处理步骤如下, (1)打开Maplex标注引擎.从ToolBars中打开Labeling工具,勾选U ...
- https://stackoverflow.com/与程序相关的IT技术问答网站
https://stackoverflow.com/ Stack Overflow是一个与程序相关的IT技术问答网站.用户可以在网站免费提交问题,浏览问题,索引相关内容,在创建主页的时候使用简单的HT ...
- <jquery>滚动例子
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...