本文将同步发布于:

  • 洛谷博客;
  • csdn;
  • 博客园;
  • 简书;

题目

题目链接:洛谷 P3122、USACO 官网。

题意概述

给你平面上的一些点和直线,有两种操作:

  • 新加入一个点 (x,y)(x,y)(x,y);
  • 给定一条直线 ax+by=cax+by=cax+by=c,询问是否所有点都在这条直线的同侧(在直线上不合法)。

初始时有 n≤105n\leq 10^5n≤105 个点,共有 q≤105q\leq 10^5q≤105 次操作。

题解

对题意转化

我们考虑将 所有点都在直线的同一侧 这一条件进行转化。

具体地,我们先考虑一个简单的子问题。

简单子问题

问题是这样的,对于一条标准形式的直线 ax+by+c=0ax+by+c=0ax+by+c=0,在它同侧的点 (xp,yp)(x_p,y_p)(xp​,yp​) 满足什么性质?

我们倒推并分类讨论:

  • 若 axp+byp+c=0ax_p+by_p+c=0axp​+byp​+c=0,显然点 (xp,yp)(x_p,y_p)(xp​,yp​) 在这条直线上;
  • 若 axp+byp+c<0ax_p+by_p+c<0axp​+byp​+c<0,显然它与所有点 qqq 满足 axq+byq+c<0ax_q+by_q+c<0axq​+byq​+c<0 在直线的同侧;
  • 若 axp+byp+c>0ax_p+by_p+c>0axp​+byp​+c>0,显然它与所有点 qqq 满足 axq+byq+c>0ax_q+by_q+c>0axq​+byq​+c>0 在直线的同侧;

因此我们发现,如果两个点在一条直线的同侧,则将两点坐标代入直线方程得到的结果同号。


解决了子问题,我们对题意进行转化,得到如下式子。

一条直线合法当且仅当

∀p∈S,sgn⁡(axp+byp−c)=sgn⁡(axq+byq−c)\forall p\in S,\operatorname{sgn}(ax_p+by_p-c)=\operatorname{sgn}(ax_q+by_q-c)∀p∈S,sgn(axp​+byp​−c)=sgn(axq​+byq​−c)

意思就是所有点对应的符号相同(暂时不考虑点在直线上)。

进一步地,一堆数同号说明它们的最大值与最小值同号。

问题转变成为,给定一条直线 ax+by−c=0ax+by-c=0ax+by−c=0,求

max⁡p∈S{axp+byp−c}\max_{p\in S}\{ax_p+by_p-c\}p∈Smax​{axp​+byp​−c}
min⁡p∈S{axp+byp−c}\min_{p\in S}\{ax_p+by_p-c\}p∈Smin​{axp​+byp​−c}

利用几何性质解决问题

先来求解最大值吧。

设直线为 ax+by−c=maxax+by-c=\texttt{max}ax+by−c=max。

先将直线转化为斜截式:

y=−abx+c+sumby=-\frac{a}{b}x+\frac{c+\texttt{sum}}{b}y=−ba​x+bc+sum​

我们发现:

  • 若 b>0b>0b>0,我们只需要最大化该直线在 yyy 轴上的截距即可,维护一个上凸包,在上凸包上二分斜率求解即可;
  • 若 b<0b<0b<0,我们则可以通过变号等方法修改成为 b>0b>0b>0 的情况;
  • 若 b=0b=0b=0,我们发现此时的最大值必定在凸包的右端点取到,若用 max\texttt{max}max 值作为判据,则不受影响,无需考虑。

再来求解最小值,还是一样的步骤:

设直线为 ax+by−c=minax+by-c=\texttt{min}ax+by−c=min。

先将直线转化为斜截式:

y=−abx+c+minby=-\frac{a}{b}x+\frac{c+\texttt{min}}{b}y=−ba​x+bc+min​

我们发现:

  • 若 b>0b>0b>0,我们只需要最小化该直线在 yyy 轴上的截距即可,维护一个下凸包,在下凸包上二分斜率求解即可;
  • 若 b<0b<0b<0,我们则可以通过变号等方法修改成为 b>0b>0b>0 的情况;
  • 若 b=0b=0b=0,我们发现此时的最小值必定在凸包的右端点取到,若用 min\texttt{min}min 值作为判据,则不受影响,无需考虑。

分治方法优化转移

上述方法需要动态维护两个凸包,并且凸包的横坐标不具有单调性,这需要用 平衡树 来维护。

考虑到本题并不强制在线,我们考虑离线下来,利用 cdq 分治来维护凸包,时间复杂度为 Θ(nlog⁡2n)\Theta(n\log^2n)Θ(nlog2n)(视作 n,qn,qn,q 同阶)。

具体地,我们考虑对点和直线的加入时间进行分治,假设当前要处理区间 [l,r][l,r][l,r] 内的事件。我们就只要考虑 区间 [l,mid][l,\texttt{mid}][l,mid] 内的点形成的凸包对 区间 [mid+1,r][\texttt{mid}+1,r][mid+1,r] 内直线的贡献即可。

维护凸包所需时间复杂度为排序的 Θ(nlog⁡2n)\Theta(n\log_2n)Θ(nlog2​n),结合主定理分析可知最终时间复杂度为 Θ(nlog⁡22n)\Theta(n\log_2^2n)Θ(nlog22​n)。

参考程序

更多细节参见参考程序。

#include<bits/stdc++.h>
using namespace std;
#define reg register
typedef long long ll;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
static char buf[1<<21],*p1=buf,*p2=buf;
#define flush() (fwrite(wbuf,1,wp1,stdout),wp1=0)
#define putchar(c) (wp1==wp2&&(flush(),0),wbuf[wp1++]=c)
static char wbuf[1<<21];int wp1;const int wp2=1<<21;
inline int read(void){reg bool f=false;reg char ch=getchar();reg int res=0;while(!isdigit(ch))f|=(ch=='-'),ch=getchar();while(isdigit(ch))res=10*res+(ch^'0'),ch=getchar();return f?-res:res;
}inline ll readll(void){reg bool f=false;reg char ch=getchar();reg ll res=0;while(!isdigit(ch))f|=(ch=='-'),ch=getchar();while(isdigit(ch))res=10*res+(ch^'0'),ch=getchar();return f?-res:res;
}inline void writeln(const char* s){while(*s) putchar(*(s++));putchar('\n');return;
}inline ll max(reg ll a,reg ll b){return a>b?a:b;
}inline ll min(reg ll a,reg ll b){return a<b?a:b;
}struct Vector{int x,y;inline Vector(reg int x=0,reg int y=0):x(x),y(y){return;}inline Vector operator+(const Vector& a)const{return Vector(x+a.x,y+a.y);}inline Vector operator-(const Vector& a)const{return Vector(x-a.x,y-a.y);}
};inline ll dot(const Vector& a,const Vector& b){return 1ll*a.x*b.x+1ll*a.y*b.y;
}inline ll cross(const Vector& a,const Vector& b){return 1ll*a.x*b.y-1ll*a.y*b.x;
}typedef Vector Point;inline bool operator<(const Point& a,const Point& b){return a.x<b.x||(a.x==b.x&&a.y<b.y);
}const int MAXN=1e5+5;
const int MAXQ=1e5+5;
const ll inf=5e18;struct updates{int tim;Point p;
};struct querys{int tim;int A,B;ll C;ll Max,Min;
};int n,q;
int totu,totq;
updates up[MAXN+MAXQ];
querys qu[MAXQ];inline ll getVal(const querys& q,const Point& p){return 1ll*q.A*p.x+1ll*q.B*p.y-q.C;
}inline void solve(reg int l,reg int r,reg int lu,reg int ru,reg int lq,reg int rq){if(l==r)return;if(lu>ru||lq>rq)return;reg int mid=(l+r)>>1;reg int midu,midq;if(up[lu].tim<=mid){reg int __l=lu,__r=ru,__mid;while(__l<__r){__mid=(__l+__r)>>1;if(up[__mid+1].tim<=mid)__l=__mid+1;else__r=__mid;}midu=__l;}elsemidu=lu-1;if(qu[lq].tim<=mid){reg int __l=lq,__r=rq,__mid;while(__l<__r){__mid=(__l+__r)>>1;if(qu[__mid+1].tim<=mid)__l=__mid+1;else__r=__mid;}midq=__l;}elsemidq=lq-1;solve(l,mid,lu,midu,lq,midq);if(lu<=midu&&midq+1<=rq){reg int tot=0;static Point tmp[MAXN+MAXQ];for(reg int i=lu;i<=midu;++i)tmp[++tot]=up[i].p;sort(tmp+1,tmp+tot+1);reg int top;static Point S[MAXN+MAXQ];top=0;for(reg int i=1;i<=tot;++i){while(top>1&&cross(S[top]-S[top-1],tmp[i]-S[top-1])>=0)--top;S[++top]=tmp[i];}for(reg int i=midq+1;i<=rq;++i){reg int __l=1,__r=top,__mid;while(__l<__r){__mid=(__l+__r)>>1;if(getVal(qu[i],S[__mid])<getVal(qu[i],S[__mid+1]))__l=__mid+1;else__r=__mid;}qu[i].Max=max(qu[i].Max,getVal(qu[i],S[__l]));}top=0;for(reg int i=1;i<=tot;++i){while(top>1&&cross(S[top]-S[top-1],tmp[i]-S[top-1])<=0)--top;S[++top]=tmp[i];}for(reg int i=midq+1;i<=rq;++i){reg int __l=1,__r=top,__mid;while(__l<__r){__mid=(__l+__r)>>1;if(getVal(qu[i],S[__mid])>getVal(qu[i],S[__mid+1]))__l=__mid+1;else__r=__mid;}qu[i].Min=min(qu[i].Min,getVal(qu[i],S[__l]));}}solve(mid+1,r,midu+1,ru,midq+1,rq);return;
}int main(void){n=read(),q=read();for(reg int i=1;i<=n;++i){++totu;up[totu].tim=0,up[totu].p.x=read(),up[totu].p.y=read();}for(reg int i=1;i<=q;++i){static int opt;opt=read();switch(opt){case 1:{++totu;up[totu].tim=i,up[totu].p.x=read(),up[totu].p.y=read();break;}case 2:{++totq;qu[totq].tim=i,qu[totq].A=read(),qu[totq].B=read(),qu[totq].C=readll(),qu[totq].Max=-inf,qu[totq].Min=inf;if(qu[totq].B<0)qu[totq].A=-qu[totq].A,qu[totq].B=-qu[totq].B,qu[totq].C=-qu[totq].C;else if((!qu[totq].B)&&qu[totq].A<0)qu[totq].A=-qu[totq].A,qu[totq].C=-qu[totq].C;break;}}}solve(0,q,1,totu,1,totq);for(reg int i=1;i<=totq;++i)writeln((!qu[i].Max||!qu[i].Min||((qu[i].Max^qu[i].Min)>>63))?"NO":"YES");flush();return 0;
}

「题解」USACO15FEB Fencing the Herd G相关推荐

  1. 「题解」300iq Contest 2 H. Honorable Mention

    本文将同步发布于: 洛谷博客: csdn: 博客园: 简书. 题目 题目链接:gym102331H. 题意概述 给定一个长度为 n n n 的序列 a a a,有 q q q 次询问,每次询问给定三个 ...

  2. 「题解」蝙蝠侠的麻烦

    没 事 找 事 「我的做题历程」: step1:观察题面.   「蝙蝠侠需要找到一个最长的字符串,使得这个字符串作为一个子序列被包含在所有的三个字符串中」,可以得出这是一道最长公共子序列,而且有三个字 ...

  3. 「题解」:[组合数学]:Perm 排列计数

    题干: Description称一个1,2,-,N的排列P1,P2-,Pn是Magic的,当且仅当2<=i<=N时,Pi>Pi/2. 计算1,2,-N的排列中有多少是Magic的,答 ...

  4. 「题解」:[BZOJ4558]方

    问题: 方 时间限制: 2 Sec  内存限制: 256 MB 题面 题目描述 上帝说,不要圆,要方,于是便有了这道题.由于我们应该方,而且最好能够尽量方,所以上帝派我们来找正方形 上帝把我们派到了一 ...

  5. 「题解」300iq Contest 2 B Bitwise Xor

    本文将同步发布于: 洛谷博客: csdn: 博客园: 简书. 题目 题目链接:gym102331B. 题意概述 给你一个长度为 nnn 的序列 aia_iai​,求一个最长的子序列满足所有子序列中的元 ...

  6. 「题解」:[线段树]:永无乡

    题面 题目描述 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过桥可以从一个岛 ...

  7. 「题解」老鼠与猫的交易

    题目描述 有一只老鼠很喜欢奶酪,但是奶酪被分别放在N个房间里,而且这些房间都有一只猫咪看守,现在它准和猫咪们 做个交易.它有M磅的猫食,想用这M磅猫食换取奶酪.在猫咪看守的每一个房间里有奶酪J[i]磅 ...

  8. 「题解」清华集训 2016 你的生命已如风中残烛

    本文将同步发布于: 洛谷博客: csdn: 博客园: 简书: 题目 题目链接:洛谷 P6672.UOJ 273. 题意简述 给你牌数为 m + 1 m+1 m+1 的牌堆,其中第 m + 1 m+1 ...

  9. 「题解」CF1468M Similar Sets

    本文将同步发布于: 洛谷博客: csdn: 博客园: 简书. 题目 题目链接:洛谷.CF1468M. 题意简述 给定 n n n 个集合 S 1 ∼ n S_{1\sim n} S1∼n​,问是否存在 ...

最新文章

  1. Ant Design 入门-引用自己命名的组件
  2. springboot解决js前端跨域问题,javascript跨域问题解决
  3. 中国WEB 2.0的质变过程
  4. winform的UI设计关键属性汇总
  5. uci数据集_干货收藏!三大领域常用十大开源数据集
  6. bootstrap3 中文手册 [下载]
  7. Java高并发入门-线程初步
  8. mysql mongodb 事务_认识MongoDB 4.0的新特性——事务(Transactions)
  9. 【Linux使用】Centos 7设置时区与时钟(chrony / ntp /systemd)
  10. 红皮书--With语句及布尔型
  11. 链表中倒数第 k 个节点
  12. ffmbc——为广播电视以及专业用途量身定制的FFmpeg
  13. SPF邮件伪造漏洞测试脚本
  14. eval函数pythonmopn_pytorch:model.train和model.eval用法及区别详解
  15. arm-4-裸板开发
  16. FFmpeg 解码 H264 格式的视频
  17. echarts地图各种点位实现
  18. Microsoft Edge浏览器黑色背景修改
  19. 如何删除重复项只保留最新项
  20. 坚定文化新自信 提升文化软实力

热门文章

  1. 【转】红帽 Red Hat Linux相关产品iso镜像下载【迅雷快传】【百度云】【更新7.1】...
  2. Joomla模板安装需安装范例数据库
  3. Windows 10 连接 Zune 直接拷歌的方法
  4. 2022隐私计算十大观察
  5. 高中教资信息技术Flash动画软件分享
  6. 设计模式与软考试题之状态模式(二)
  7. Hyperledger技术简介
  8. 2021.11.17洛谷小鱼游泳进阶版——c语言
  9. 【历史上的今天】11 月 12 日:USB 3.0 发布;图灵机论文被发表;TinyOS 创作者诞生
  10. CPU、MPU、MCU、SoC、MCM介绍