传送门

思路简单码量超凡?

感觉看完题大家应该都知道是倍增sbsbsb题了吧。

首先预处理出从每个点出发如果是AAA走到哪个点,如果是BBB走到哪个点。

然后利用刚刚预处理出的信息再预处理从每个点出发AAA走2i2^i2i次的距离,BBB走2i2^i2i次的距离,A,BA,BA,B走2i2^i2i轮之后到了哪个点。

剩下的询问就跑倍增就行了。

代码:

#include<bits/stdc++.h>
#include<tr1/unordered_map>
#define fi first
#define se second
using namespace std;
inline int read(){
	int ans=0,w=1;
	char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return ans*w;
}
typedef pair<int,int> pii;
const int N=1e5+5;
int Ans=0,ansa=0x3f3f3f3f,ansb=0,x0,n,m,h[N],st[N][21],disa[N][21],disb[N][21],nxta[N],nxtb[N];
struct Node{
	int id,val;
	friend inline bool operator<(const Node&a,const Node&b){return a.val==b.val?h[a.id]<h[b.id]:a.val<b.val;}
};
inline void init(){
	set<pii>S;
	int tot=0;
	Node tmp[5];
	tot=0;
	for(int pos=n;pos;--pos){
		S.insert(pii(h[pos],pos));
		if(pos==n)continue;
		tot=0;
		set<pii>::iterator it=S.find(pii(h[pos],pos));
		if(it!=S.begin()){
			--it,tmp[++tot]=(Node){it->se,h[pos]-it->fi};
			if(it!=S.begin())--it,tmp[++tot]=(Node){it->se,h[pos]-it->fi},++it;
			++it;
		}
		if((++it)!=S.end()){
			tmp[++tot]=(Node){it->se,it->fi-h[pos]};
			if((++it)!=S.end())tmp[++tot]=(Node){it->se,it->fi-h[pos]};
		}
		sort(tmp+1,tmp+tot+1);
		nxtb[pos]=tmp[1].id;
		if(tot^1)nxta[pos]=tmp[2].id;
	}
	for(int i=1;i<=n;++i){
		int p1=nxta[i],p2=nxtb[p1];
		disa[i][0]=p1?abs(h[p1]-h[i]):0,disb[i][0]=p2?abs(h[p1]-h[p2]):0,st[i][0]=p2;
	}
	for(int j=1;j<=20;++j)for(int i=1;i<=n;++i){
		st[i][j]=st[st[i][j-1]][j-1];
		disa[i][j]=disa[i][j-1]+disa[st[i][j-1]][j-1];
		disb[i][j]=disb[i][j-1]+disb[st[i][j-1]][j-1];
	}
}
inline pii solve(int s,int dis){
	pii ret=pii(0,0);
	for(int i=20;~i;--i)if(st[s][i]&&disa[s][i]+disb[s][i]<=dis)dis-=disa[s][i]+disb[s][i],ret.fi+=disa[s][i],ret.se+=disb[s][i],s=st[s][i];
	if(!nxta[s]||abs(h[nxta[s]]-h[s])>dis)return ret;
	return ret.fi+=abs(h[nxta[s]]-h[s]),ret;
}
int main(){
	n=read();
	for(int i=1;i<=n;++i)h[i]=read();
	init(),x0=read();
	pii ans;
	for(int i=1;i<=n;++i){
		pii res=solve(i,x0);
		if(!Ans||((long long)ansa*res.se>(long long)ansb*res.fi))ansa=res.fi,ansb=res.se,Ans=i;
	}
	printf("%d\n",Ans);
	for(int i=read(),x,s;i;--i)s=read(),x=read(),ans=solve(s,x),printf("%d %d\n",ans.fi,ans.se);
	return 0;
}

2018.11.04 洛谷P1081 开车旅行(倍增)的更多相关文章

  1. 洛谷 P1081 开车旅行 —— 倍增

    题目:https://www.luogu.org/problemnew/show/P1081 真是倍增好题! 预处理:f[i][j] 表示从 i 点开始走 2^j 次 AB (A,B各走一次)到达的点 ...

  2. 洛谷P1081 开车旅行(倍增)

    题意 题目链接 Sol 咕了一年的题解.. 并不算是很难,只是代码有点毒瘤 \(f[i][j]\)表示从\(i\)号节点出发走了\(2^j\)轮后总的距离 \(da[i][j]\)同理表示\(a\)的 ...

  3. 洛谷 P1081 开车旅行(70)

    P1081 开车旅行 题目描述 小AA 和小BB 决定利用假期外出旅行,他们将想去的城市从 11到 NN 编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 ii的海 ...

  4. [NOIP2012] 提高组 洛谷P1081 开车旅行

    题目描述 小 A 和小 B 决定利用假期外出旅行,他们将想去的城市从 1 到 N 编号,且编号较小的 城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 i 的海拔高度为 Hi,城市 ...

  5. NOIP 2012 洛谷P1081 开车旅行

    Description: 就是两个人开车,只能向东开.向东有n个城市,城市之间的距离为他们的高度差.A,B轮流开车,A喜欢到次近的城市,B喜欢到最近的城市.如果车子开到底了或者车子开的路程已经超过了限 ...

  6. 2018.11.04 洛谷P2679 子串(线性dp)

    传送门 为什么前几年的noipnoipnoip总是出这种送分题啊? 这个直接线性dpdpdp不就完了吗? f[i][j][k][0/1]f[i][j][k][0/1]f[i][j][k][0/1]表示 ...

  7. 洛谷P1081 开车旅行70分

    https://www.luogu.org/problem/show?pid=1081 太遗憾了明明写出来了,却把最小值初始值弄小了,从第二个点开始就不可能对了.70分! #include<io ...

  8. 洛谷 P1081 开车旅行【双向链表+倍增】

    倍增数组的20和N写反了反复WAWAWA-- 注意到a和b在每个点上出发都会到一个指定的点,所以这样构成了两棵以n点为根的树 假设我们建出了这两棵树,对于第一问就可以枚举起点然后倍增的找出ab路径长度 ...

  9. 洛谷P1081 开车旅行

    题目 双向链表+倍增+模拟. \(70pts\): 说白了此题的暴力就是细节较多的模拟题. 我们设离\(i\)城市最近的点的位置为\(B[i]\),第二近的位置为\(A[i]\).设\(A\)或\(B ...

随机推荐

  1. linux命令学习之:systemctl

    systemctl命令是系统服务管理器指令,主要负责控制systemd系统和服务管理器,它实际上将 service 和 chkconfig 这两个命令组合到一起. CentOS 7.x开始,CentO ...

  2. xshell实时跟踪日志与中文乱码设置

    1.实时跟踪日志命令 tail -f logName.log 动态查看名为logName的日志信息 ctrl+c 退出实时跟踪 2.中文乱码设置 在Xshell.putty.SSH Secure Sh ...

  3. avalon子孙元素属性监听

    HTML正文: <body ms-controller="ex"> <div class="ms-hover" ms-click=" ...

  4. oracle学习之数据库数据保存成文件

    常常需要将数据库中的数据生成文档,由于比较喜欢脚本的方式,所以就需要使用spool的时候进行格式设置,以下简单整理了一下oracle中进行格式设置的一些东西,一共十八条,其实常用的也就那么几个,稍后会 ...

  5. [z]一分钟教你知道乐观锁和悲观锁的区别

    悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁.传统的关系型数据 ...

  6. python学习笔记Day3

    set有点:1.访问速度快 2.天生解决了重复问题 tuple与set区别: 元组可重复,set不可重复创捷集合1 >>> s1.add('alex')>>> pr ...

  7. Android Studio 发布 APK

    打开发布设置窗口 打开Generate Signed APK...窗口,点击Create new... 打开Create New...窗口,创建一个Key,这个Key的相关信息一定要好好保存,因为以后 ...

  8. Linux下查看系统启动 、运行以及安装时间

    1.uptime命令  例子显示已启动13天 当前用户一个 [root@localhost-live version-build-related]# uptime :: up days, :, use ...

  9. [转载]linux awk命令详解

    简介 awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大.简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再 ...

  10. 放大Button热区的方法哟

    //添加图片不能用backgroundimage [btn setImage:image5 forState:]; //然后 btn.imageEdgeInsets = UIEdgeInsetsMak ...