【XJOI】山

2023-10-30 05:30
文章标签 xjoi

本文主要是介绍【XJOI】山,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目链接(咕咕咕。。。)

题目描述:

xyz现在站在一个斜坡面前这个斜坡上依次排布这\(n\)座山峰,xyz打算爬上其中的一座因为xyz体力不好,所以他只能爬上最矮的一座山又因为xyz不擅长分类讨论,因此即使山的海拔为负,他也只打算爬海拔最低的那座,而不是海拔的绝对值最小的那座然而xyz智商拙计,只带了一张相对海拔高度地图,于是要来求助你现在他知道这个斜坡有\(m\)种可能的斜率,请你对于每种斜率输出海拔最低的山峰的高度我们定义每两座山之间的水平距离都为1,第0座山所在的土地海拔高度为0

输入格式:

第一行两个数\(n\),\(m\)
第二行有\(n\)个数,表示每座山峰的高度
接下来\(m\)行每行有一个数\(p\),表示这个斜坡可能的斜率(可能小于0)

输出格式:

对于每个询问输出一行,表示最矮的山峰的海拔高度

样例输入:

3 1
3 2 1
10

样例输出:

13

数据范围:

30%的数据 \(n,m<=1000\)
100%的数据 \(n,m<=300000,max(|h[i]|)<10^12,max(|h[i]+i*p|)<10^18\),

时间限制:

1s

空间限制:

64MB

提示:

remove!!!

题解

\(n\)座山峰,还有一个斜率,求每个山峰加上它到0的距离乘上斜率的值后的最小山峰。
因为山峰的高度是相对的,所以加上的斜率只要是相对的就行了,就相当于以斜率这条直线为标准,求最下面的那个点。
如图:斜率为正,红色为山顶到斜率的距离,蓝色为最低的山顶。
斜率为正时,与原来相比左边比右边增加的高度更少,也就是左边的山底比右边的山底相对于标准线更低,所以标准线是左边高右边低的。
标准线平移没有影响。
lVUIjiouMXHB5bE.png
我们把山只留下山顶作为二维平面上的一个点,而把斜率看成是旋转平面的操作,
手膜以下旋转的过程,每次的\(ans\)都是最下面的那个点,把这些点连起来貌似就是一个下凸壳,
那么只要斜率在一个点和它左边的点的斜率以及这个点和它右边的点的斜率的中间,那么这个点就是\(ans\)了。
那么我们就可以用二分,用\(\log_{2}n\)的时间求出\(ans\)就行了。
预处理凸包时间复杂度为\(O(n)\),询问的时间复杂度为\(m\log_{2}n\),不会TLE。
注意:山的高度在\(10^18\)以内,所以要用\(long long\)
上代码:

#include<bits/stdc++.h>
#define inf 1e18+1
using namespace std;
int n,m;
long long a[300009];
long long mn,xmn;
long long p;
struct aa{long long h,x;
}pp[300009];
int lp=2;
bool pd(int x,int l){if(l<2) return 0;return 1.0*(a[x]-pp[lp].h)/(x-pp[lp].x)<1.0*(pp[lp].h-pp[lp-1].h)/(pp[lp].x-pp[lp-1].x);
}
double xl(int x1,long long h1,int x2,long long h2){if(x1==x2){if(h1>h2) return inf;return -inf;}return 1.0*(h1-h2)/(x1-x2);
}
int main(){scanf("%d%d",&n,&m);for(int j=1;j<=n;j++)scanf("%lld",&a[j]);pp[1].h=a[1];pp[2].h=a[2];pp[1].x=1;pp[2].x=2;for(int j=3;j<=n;j++){while(pd(j,lp)) lp--;pp[++lp].x=j;pp[lp].h=a[j];}pp[0]=pp[1];pp[lp+1]=pp[lp];pp[0].h=pp[lp+1].h=inf;while(m--){scanf("%lld",&p);p=-p;int l=1,r=lp,ans;while(l<=r){int mid=(l+r)/2;if(p>=xl(pp[mid].x,pp[mid].h,pp[mid-1].x,pp[mid-1].h) && p<=xl(pp[mid+1].x,pp[mid+1].h,pp[mid].x,pp[mid].h)){ans=mid;break;}else if(p<xl(pp[mid].x,pp[mid].h,pp[mid-1].x,pp[mid-1].h)) r=mid-1;else l=mid+1;}printf("%lld\n",pp[ans].h-pp[ans].x*p);}return 0;
}

转载于:https://www.cnblogs.com/linjiale/p/11303049.html

这篇关于【XJOI】山的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/305871

相关文章

xjoi题库一级九段题解(c语言版)

金字塔 时间:0.1s   空间:128M 题目描述: 小明发现电脑可以打印出一些简单有趣的图形,比如金字塔: ********* 小明希望能够过更便捷的打印出金字塔,比如输入n,就输出高度为n的金字塔。请你帮助小明实现。 输入格式: 仅一个正整数 n 输出格式: 共n行,组成如题干描述的金字塔形状。 样例输入1: 4 样例输出1: **************** 约定:

xjoi题库一级八段题解(c语言版)

求和 时间:1s   空间:128M 题目描述: 给你n个数,求出它们的和 输入格式: 第一行输入一个整数n,表示数的个数 接下来n行,每行一个数,表示要加起来的数。 输出格式: 输出n个整数的和 样例输入1: 41234 样例输出1: 10 样例输入2: 53645-1 样例输出2: 17 约定: 1<=n<=100000 -1000000<=输入的整数<=10

XJOI一级一段题解(g++,即C++),也可视作C++算法竞赛教程

目录 Problem 9291 Hello OI 一 题目内容 二 新知识点 2.1 头文件  2.2 命名空间 2.3 注释 2.4 主函数 2.5 标准输出流 三 思路 四 AC代码 Problem 3566 学整数 一 题目内容 二 新知识点 2.1 变量与数据类型 2.2 标准输入流 三 思路 四 AC代码 Problem 1000 萌新关爱之-A+B