首页 > 其他分享 >题解:CF70D Professor's task

题解:CF70D Professor's task

时间:2024-08-25 21:04:22浏览次数:8  
标签:包中 return 题解 Professor 凸包 bool vec auto CF70D

题意

实现以下两种操作:

  1. 往点集 \(S\) 中添加一个点 \((x,y)\)。

  2. 询问点 \((x,y)\) 是否在点集 \(S\) 的凸包中。

分析

动态凸包板子。

建议先完成 P2521 [HAOI2011] 防线修建

上题维护的是上半个凸包,本题维护上下两个。

将凸包中的点按 \(x\) 排序,通过 \((x,y)\) 前驱和后继连成的直线判断 \((x,y)\) 是否位于凸包内。

若在凸包外,则加入这个点,并删除当前凸包中所有不符合凸包性质的点。


考虑使用平衡树。

既然只用查前驱和后继,用 set 就能解决。

为了便于计算,定义结构体 vec

struct vec
{
    double x, y;
    vec(double X=0, double Y=0): x(X), y(Y) {}
    friend vec operator-(vec a, vec b) {return {a.x-b.x, a.y-b.y};}
    friend double cross(vec a, vec b) {return a.x*b.y-a.y*b.x;}
    bool operator<(vec b) const {return x<b.x;}
};

因为要维护上下两个凸包,再封装一个结构体存凸包。

struct convex_hull:set<vec>
{
    auto pre(iterator it) {return --it;}
    auto aft(iterator it) {return ++it;}

    bool is_up; // 记录该凸包为上凸包还是下凸包
    convex_hull(bool x): is_up(x) {}

通过前驱和后继检查该点是否在凸包内:

bool chk(vec A)
{
    auto it=lower_bound(A);
    if(it==end()) return 0;
    if(it->x==A.x) 
        return is_up?it->y>=A.y:it->y<=A.y;
    if(it==begin()) return 0;
    vec B=*it, C=*--it;
    double st=cross(B-A, B-C);
    return is_up?st<=0:st>=0;
}

从凸包中移除一个点:

bool remove(set<vec>::iterator it)
{
    if(it==begin()) return 0;
    auto itl=pre(it);
    auto itr=aft(it);
    if(itr==end()) return 0;
    vec a=*it-*itl, b=*itr-*it;
    if(is_up?cross(a, b)<0:cross(a, b)>0) return 0;
    return erase(it), 1;
}

向凸包中加入一个点:

void append(vec A)
{
    if(chk(A)) return;
    auto it=find(A);
    if(it!=end()) erase(it);
    it=insert(A).first;
    while(it!=begin()&&remove(pre(it)));
    while(aft(it)!=end()&&remove(aft(it)));
}

每个点最多进一次凸包点集,也最多出一次凸包点集,时间复杂度 \(O(n\log n)\)。

AC 记录

标签:包中,return,题解,Professor,凸包,bool,vec,auto,CF70D
From: https://www.cnblogs.com/redacted-area/p/18379566

相关文章

  • 题解: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......
  • SP666 VOCV - Con-Junctions 题解
    注意到这个问题具有最优子结构性,考虑树上dp。记$dp[i][0/1]$表示i号节点不放灯或放灯的最小值,$s[i][0/1]$为对应的方案数。那么我们可以进行如下转移:$dp[u][0]=\sum_{u->v}dp[v][1]$$dp[u][1]=\sum_{u->v}\min(dp[v][0],dp[v][1])$在更新对应的dp数组时,我们用......
  • P9482 [NOI2023] 字符串 题解
    题目描述\(T\)组数据,给定长为\(n\)的字符串\(s\),\(q\)次询问,给定\(i,r\),求有多少个\(l\)满足:\(1\lel\ler\)。\(s[i:i+l-1]\)字典序小于\(R(s[i+l:i+2l-1])\)。数据范围\(1\leT\le5,1\len,q\le10^5,1\lei+2r-1\len\)。时间限制\(\texttt{1s}\),......
  • Triple Attack 题解
    直接暴力显然不可行。我们容易发现,变量\(T\)的增量以\(3\)为循环,一次循环会造成\(5\)的贡献,所以我们容易想到对每个\(a_i\)直接对\(5\)计算倍数和取余,然后对于余数分类讨论去增加,然后对于倍数部分统一增加即可。有些细节。Code#include<bits/stdc++.h>//#include......