首页 > 其他分享 >题解:P7401 [COCI2020-2021#5] Planine

题解:P7401 [COCI2020-2021#5] Planine

时间:2024-08-25 21:05:11浏览次数:6  
标签:COCI2020 山谷 int 题解 back && f64 Planine ds

题意

现有一座上下起伏的山。它可以抽象为一个包含 \(n\)(\(n\) 为奇数)个点 \((x_i,y_i)\) 以及 \((x_1,-\inf)\) 与 \((x_n,-\inf)\) 的多边形。

对于所有满足 \(i \neq 1\),\(i \neq n\),\(i \bmod 2=1\) 的整数 \(i\),\((x_i,y_i)\) 都是山谷。

现要放置若干个高度为 \(h\) 的点光源,使得所有的山谷都被照亮,即点光源与山谷的连线不经过山的内部。

求所需点光源的最少数量。

分析

考虑对每个山谷处理出能照亮它的点集。

比如对于如下山谷:

处理出第 \(2\) 个山谷能照亮它的点集,显然是一条在直线 \(y=h\) 上的线段:

对于第 \(2\) 个山谷而言,能照亮它的点集只受前后紧邻点的限制。

但是第 \(3\) 个山谷就有点区别了:

我们发现它还受另外的点的限制。

考虑维护一个凸包,如下图:

点集所受的限制就是凸包中最后一条边。

所以我们正向扫一遍,维护一个凸包,再反向扫一遍,维护另一个凸包即可。

时间复杂度 \(O(n)\)。


现在我们得到了若干个区间,我们需要选取若干个点,使得每个区间内至少存在一个点,并最小化点的个数。

这是一个比较经典的贪心问题。

考虑按右端点从小到大排序,每次选取右端点最小的区间,并去除所有与该区间相交的区间。

答案即为选取的次数。

正确性显然。

Code

#include<bits/stdc++.h>
using namespace std;
#define maxn 1000006
typedef long double f64_t;

struct dot{int x, y;}ds[maxn];
f64_t slope(dot a, dot b) {return (f64_t)(a.y-b.y)/(a.x-b.x);}

struct segement
{
    f64_t l, r;
    segement(f64_t x=0, f64_t y=0): l(x), r(y) {}
    friend bool operator<(segement a, segement b) {return a.r<b.r; }
}seg[maxn];

vector<int> s;
#define chk(x) ((x)!=1&&(x)!=n&&((x)&1))
f64_t back() {return slope(ds[*s.rbegin()], ds[*(s.rbegin()+1)]);}

int main()
{
    int n, h;
    cin>>n>>h;
    for(int i=1;i<=n;i++) cin>>ds[i].x>>ds[i].y;
    for(int i=1;i<=n;i++)
    {
        while(s.size()>1&&back()<=slope(ds[s.back()], ds[i])) 
            s.pop_back();
        s.emplace_back(i);
        if(chk(i)) 
        {
            f64_t k=back();
            f64_t b=ds[i].y-k*ds[i].x;
            seg[i].l=(h-b)/k;
        }
    }
    s.clear();
    for(int i=n;i;i--)
    {
        while(s.size()>1&&back()>=slope(ds[s.back()], ds[i])) 
            s.pop_back();
        s.emplace_back(i);
        if(chk(i)) 
        {
            f64_t k=back();
            f64_t b=ds[i].y-k*ds[i].x;
            seg[i].r=(h-b)/k;
        }
    }
    vector<segement> vc;
    for(int i=3;i<n;i+=2) 
        vc.emplace_back(seg[i]);
    sort(vc.begin(), vc.end());
    f64_t mxr=-1e18;
    int ans=0;
    for(auto [l, r]:vc) 
        if(l-1e-8>mxr) mxr=r, ans++;
    cout<<ans;
}

标签:COCI2020,山谷,int,题解,back,&&,f64,Planine,ds
From: https://www.cnblogs.com/redacted-area/p/18379564

相关文章

  • 题解:SP1182 SORTBIT - Sorted bit squence
    题意将区间\([m,n]\)的所有整数按照其二进制位表示的数中\(1\)的数量从小到大排序。如果\(1\)的数量相同,则按照数的大小排序。求序列中第\(k\)个数。其中,负数使用补码来表示:一个负数的二进制数与其相反数的二进制数之和恰好等于\(2^{32}\)。分析考虑用uint32_t存......
  • 题解:P3266 [JLOI2015] 骗我呢
    题意有一个\(n\timesm\)的数组\(x_{i,j}(1\lei\len,1\lej\lem)\),满足:\(x_{i,j}\in[0,m]\)\(\foralli\in[1,n],\forallj\in[1,m),x_{i,j}<x_{i,j+1}\)\(\foralli\in(1,n],\forallj\in[1,m),x_{i,j}<x_{i-1,j+1}\)......
  • 题解:CF70D Professor's task
    题意实现以下两种操作:往点集\(S\)中添加一个点\((x,y)\)。询问点\((x,y)\)是否在点集\(S\)的凸包中。分析动态凸包板子。建议先完成P2521[HAOI2011]防线修建。上题维护的是上半个凸包,本题维护上下两个。将凸包中的点按\(x\)排序,通过\((x,y)\)前驱......
  • 题解:P2521 [HAOI2011] 防线修建
    题意给定若干个点,实现下列操作:删除一个点。查询上凸包的周长。分析建议先完成【模板】二维凸包。对于这个删除操作,我们没有好的方法去在线维护它。考虑离线询问。这样删除操作就变成了插入操作。插入一个新点有如下两种情况:新点在凸包内。新点在凸包外。我们回忆......
  • 题解:CF235C Cyclical Quest
    题意给定一个主串\(S\)和\(n\)个询问串,求每个询问串的所有循环同构在主串中出现的次数总和。分析后缀自动机好题。循环同构的过程可以看作从该串的头部删除一个字符,并在尾部加入一个字符。在后缀自动机上,跳parent树的过程就相当于删除头部的若干个字符。所以我们可......
  • 7z解压crc错误_7-Zip - 常见问题解答
    7z解压crc错误_7-Zip-常见问题解答7z解压crc错误_7-Zip-常见问题解答1.引言1.17-Zip简介1.2CRC错误概述2.7z文件和CRC错误2.1什么是7z文件2.2CRC错误的定义2.3CRC错误对文件的影响3.常见原因分析3.1文件传输过程中的错误3.2存储介质的损坏3.3不兼容的压......
  • 题解:P5680 [GZOI2017] 共享单车
    题目分析出题人是擅长隐藏题意的建树首先给你一张无向图,然后指定一个根节点\(k\),从根节点开始沿最短路到每一个节点。如果到某个节点有多条最短路径,选择上一个节点编号最短的。考虑记录前驱的Dijkstra。namespaceDJ{intdis[maxn],pre[maxn],val[maxn],vis[maxn]......
  • 题解:SP22382 ETFD - Euler Totient Function Depth
    题目链接:link,点击这里喵。前置知识:【模板】线性筛素数,欧拉函数,点击这里喵。题意简述:给定整数$l,r,k$,求出$[l,r]$中有多少个整数不断对自己取欧拉函数刚好$k$次结果为$1$。思路:看眼数据范围,$10^{10}$的量级显然不容我们每次暴力,故考虑预处理$\varphi(i),can(i,k),su......
  • 【面试系列】大数据平台常见面试题解答
    欢迎来到我的博客,很高兴能够在这里和您见面!欢迎订阅相关专栏:工......
  • AtCoder ABC 368题解
    前言本题解部分思路来自于网络。A-Cut题目大意有\(n\)张卡片叠在一起,从上到下给出\(n\)卡片的编号,将\(k\)张卡片从牌堆底部放到顶部后,从上到下输出卡片的编号。解题思路按照题意模拟即可。code#include<bits/stdc++.h>usingnamespacestd;inta[105];intmai......