首页 > 其他分享 >CF70D Professor's task 题解 & 动态凸包板子

CF70D Professor's task 题解 & 动态凸包板子

时间:2023-09-17 11:23:00浏览次数:45  
标签:pre return 题解 Professor pos 凸包 second top first

CF70D Professor's task 题解

前言

此篇题解用的是 \(Andrew\),不想看这种做法的可以绕道。

题意

动态凸包板子题。

维护动态凸包。两种操作,加一个点或查询一个点是否在凸包内。

题解

首先你得会静态二维凸包

维护二维凸包的方法挺多的,比如什么 \(Andrew\) 算法,\(Jarvis\) 算法还有 \(Graham\) 扫描法,极角法(当然我个人认为极角法不太好,掉精啥的麻烦),在二维凸包板子题的题解里里有一位大佬写的非常好,给个链接(会的可以略过此部分)。

我觉得 \(Andrew\) 好打还方便 就会这一个 所以这里用的 \(Andrew\) 算法。

考虑怎么维护动态的凸包。

对于查询,我们比较好办,只需要查一下它是不是在下凸壳上面并且在上凸壳下面,如果是,那就在里面,不是,则不在。

怎么查?向量积(叉乘)呗。\(check\) 函数不就出来了吗。

那怎么加点?

先想想静态凸包我们干了点什么:

  1. 以横坐标为第一关键字,纵坐标为第二关键字排了遍序;

  2. 每次叉乘判断是否加入一个新点;

  3. 加入的过程中弹出原来的不是最优的点。

所以我们现在也需要维护这些东西:

  1. 需要一直保证有序,于是选用 \(map\),方便一会用指针遍历,也能保证有序;

  2. 加入新点也是一样的,还是叉乘判断;

  3. 弹出有点麻烦,不想原来那样打个指针走就行,这次得打个函数,因为我们需要维护那个 \(map\)。

就没了。

总结一下:\(check\) 函数,\(insert\) 函数,\(remove\) 函数,上凸壳和下凸壳都各自需要这三个函数,所以总共是 \(6\) 个。具体细节见代码。

说一下时间复杂度。

第一篇题解的时间复杂度讲的有点,,,反正我猛一下没看懂,但是还是比较好分析的。

每一个点最多都会加一次再弹出一次,单次加进去和单次弹出都是 \(O(logn)\),于是总的就是 \(O(nlogn)\)。

代码

//https://www.luogu.com.cn/problem/CF70D CF70D Professor's task
#include <bits/stdc++.h>
#define int long long
#define P pair<int, int>
#define MP make_pair

using namespace std;

int n;
map<int, int> top, bottom;

P operator - (P x, P y) {return {y.first - x.first, y.second - x.second};}

inline int cross(P x, P y) {return x.first * y.second - x.second * y.first;}

inline bool check_top (int x, int y) {
    auto pos = top.lower_bound(x);
    if(pos == top.end())
        return false;
    if(pos -> first == x)
        return y <= pos -> second;
    if(pos == top.begin())
        return false;
    auto pre = pos;
    -- pre;
    return cross(MP(pre -> first, pre -> second) - MP(pos -> first, pos -> second), MP(pre -> first, pre -> second) - MP(x, y)) <= 0;
}

inline bool check_bottom(int x, int y) {
    auto pos = bottom.lower_bound(x);
    if(pos == bottom.end())
        return false;
    if(pos -> first == x)
        return y >= pos -> second;
    if(pos == bottom.begin())
        return false;
    auto pre = pos;
    -- pre;
    return cross(MP(pre -> first, pre -> second) - MP(pos -> first, pos -> second), MP(pre -> first, pre -> second) - MP(x, y)) >= 0;
}

inline bool remove_top(map<int, int>::iterator pos) {
    if(pos == top.begin())
        return false;
    auto pre = pos, nex = pos;
    -- pre, ++ nex;
    if(nex == top.end())
        return false;
    if(cross(MP(pre -> first, pre -> second) - MP(pos -> first, pos -> second), MP(pre -> first, pre -> second) - MP(nex -> first, nex -> second)) < 0)
        return false;
    top.erase(pos);
    return true;
}

inline bool remove_bottom(map<int, int>::iterator pos) {
    if(pos == bottom.begin())
        return false;
    auto pre = pos, nex = pos;
    -- pre, ++ nex;
    if(nex == bottom.end())
        return false;
    if(cross(MP(pre -> first, pre -> second) - MP(pos -> first, pos -> second), MP(pre -> first, pre -> second) - MP(nex -> first, nex -> second)) > 0)
        return false;
    bottom.erase(pos);
    return true;
}

inline void add_top(int x, int y) {
    if(check_top(x, y))
        return;
    top[x] = y;
    auto pos = top.find(x), ji = pos;
    if(pos != top.begin()) {
        -- ji;
        while(remove_top(ji ++))
            -- ji;
    }
    if(++ ji != top.end())
        while(remove_top(ji --))
            ++ ji;
}

inline void add_bottom(int x, int y) {
    if(check_bottom(x, y))
        return;
    bottom[x] = y;
    auto pos = bottom.find(x), ji = pos;
    if(pos != bottom.begin()) {
        -- ji;
        while(remove_bottom(ji ++))
            -- ji;
    }
    if(++ ji != bottom.end())
        while(remove_bottom(ji --))
            ++ ji;
}

signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    cin >> n;
    for(int i = 1; i <= n; ++ i) {
        int op, x, y;
        cin >> op >> x >> y;
        if(op == 1) {
            add_top(x, y);
            add_bottom(x, y);
        }
        else {
            if(check_top(x, y) && check_bottom(x, y))
                cout << "YES\n";
            else
                cout << "NO\n";
        }
    }
}

标签:pre,return,题解,Professor,pos,凸包,second,top,first
From: https://www.cnblogs.com/Meteor-streaking/p/17707986.html

相关文章

  • 简单分治快排问题解析(c++实现)
    这几天刷了需要使用分治快排思想去解决的几道比较好的题目,所以写下这篇博客用于复习和以后的复盘。什么是分治快排思想首先我们要知道什么是分治快排思想,这个思想其实就是在模拟实现qsort算法的时候使用的一个方法,在模拟实现qsort的时候,我们知道第一步是需要使用一个随意选择(三数取......
  • [ABC320E] Somen Nagashi题解
    2023-09-16题目题目传送门翻译翻译难度&重要性(1~10):4题目来源AtCoder题目算法优先队列解题思路水题一道。需要两个优先队列:因为每一次是队首的人拿到面条,即队列中编号最小的拿面条,就用一个优先队列用来维护当前队列中的编号最小的人。由于每一次拿了面条后再......
  • [ABC320F] Fuel Round Trip 题解
    题意在坐标轴上给定\(N\)个点,坐标依次为\(X_1,X_2,\cdots,X_N\),你需要从原点前往\(X_N\)并折返,其中在第\(1\)个到第\(N-1\)个点上有加油站,其中第\(i\)个加油站可以花费\(P_i\)购买\(F_i\)升汽油,汽油持有上限为\(H\)升,每行驶一单位距离需要花费一升汽油。在......
  • 【题解】AtCoder-ABC320
    AtCoder-ABC320ALeylandNumber依题意计算。提交记录:Submission-AtCoderAtCoder-ABC320BLongestPalindrome直接\(O(n^2)\)枚举,\(O(n)\)判断。提交记录:Submission-AtCoderAtCoder-ABC320CSlotStrategy2(Easy)不妨将字符串复制三遍,枚举\([0,3m)\)判断。提交......
  • 【POJ 3275】Ranking the Cows 题解(传递闭包)
    农夫约翰的N头奶牛(1≤N≤1000)产奶率各不相同,FJ希望根据这些比率从最快的奶牛到最慢的奶牛订购奶牛。FJ已经比较了M(1≤M≤10000)对奶牛的产奶率。他想列出另外C对奶牛的列表,这样,如果他现在比较这些C对奶牛,他肯定能够推断出所有N头牛的正确顺序。请帮助他确定C的最小值,这样的列表是可......
  • 合并果子题解-C++ STL priority_queue容器的使用
    说明:本博文关于priority_queue容器的说明来源于www.cnblogs.com/fusiwei/p/11823053.html本人是刚刚接触算法竞赛的萌新,如果有大佬发现了错误,还望指出(真的有人会看本蒟蒻的博文吗)这是我的第一篇博文,更多是作为测试以后会将博客作为笔记记录学习的体会基本概念priority_queu......
  • lattice crosslink开发板mipi核心板csi测试dsi屏lif md6000 fpga 常见问题解答
    1.概述    CrossLink开发板,是用Lattice的芯片CrossLink家族系列的,LIF-MD6000-6JM80I。该芯片用于桥接视频接口功能,自带2路MIPI硬核的功能,4LANE MIPI的功能,支持高速率1.5Gbps。   其他普通IO支持1.2Gbps速率,支持5路MIPI通道功能。 芯片包含LVDS,SLVS200,SubL......
  • 华为应用市场上架 视频介绍上传 遇到的问题解决
    昨天在华为应用市场上架应用, 视频介绍上传时, 一直是视频加载中,百思不得其解. 虽然不是第一次上传视频了,怎么这次遇到这个问题.偶然发现在视频介绍上传时, 选择海报后,一定要下划,点击确认,才能完成上传!否则一直是视频加载中............
  • AnyCAD程序无法启动的问题解决方法
    在某些电脑上会出现基于AnyCAD开发的程序无法启动的问题,如:System-ArgumentEcception:Pleasecheckthedependendes解决方法安装最新的VS运行时库,如VS2022:微软官方下载地址:x64:vc_redist.x64.exeSystem.AccessViolationException:"Attemptedtoreadorwriteprotected......
  • CF1542E1 Abnormal Permutation Pairs (easy version) 题解
    CF1542E1AbnormalPermutationPairs(easyversion)题解不会Hardversion对于第一个限制字典序,我们可以考虑枚举前\(i\)位相同,然后考虑后\(n-i\)位。我们只需要保证\(p_{i+1}<q_{i+1}\)即可。我们设\(len=n-i\)。由于前\(i\)位完全相同,所以前\(i\)位内部......