本文将同步发布于:

题目

题目链接:洛谷 P3122USACO 官网

题意概述

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

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

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

题解

对题意转化

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

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

简单子问题

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

我们倒推并分类讨论:

  • 若 \(ax_p+by_p+c=0\),显然点 \((x_p,y_p)\) 在这条直线上;
  • 若 \(ax_p+by_p+c<0\),显然它与所有点 \(q\) 满足 \(ax_q+by_q+c<0\) 在直线的同侧;
  • 若 \(ax_p+by_p+c>0\),显然它与所有点 \(q\) 满足 \(ax_q+by_q+c>0\) 在直线的同侧;

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


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

一条直线合法当且仅当

\[\forall p\in S,\operatorname{sgn}(ax_p+by_p-c)=\operatorname{sgn}(ax_q+by_q-c)
\]

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

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

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

\[\max_{p\in S}\{ax_p+by_p-c\}
\]
\[\min_{p\in S}\{ax_p+by_p-c\}
\]

利用几何性质解决问题

先来求解最大值吧。

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

先将直线转化为斜截式:

\[y=-\frac{a}{b}x+\frac{c+\texttt{sum}}{b}
\]

我们发现:

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

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

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

先将直线转化为斜截式:

\[y=-\frac{a}{b}x+\frac{c+\texttt{min}}{b}
\]

我们发现:

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

分治方法优化转移

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

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

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

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

参考程序

更多细节参见参考程序。

#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;
}
else
midu=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;
}
else
midq=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. 「题解」「美团 CodeM 资格赛」跳格子

    目录 「题解」「美团 CodeM 资格赛」跳格子 题目描述 考场思路 思路分析及正解代码 「题解」「美团 CodeM 资格赛」跳格子 今天真的考自闭了... \(T1\) 花了 \(2h\) 都没有搞 ...

  2. 「题解」「HNOI2013」切糕

    文章目录 「题解」「HNOI2013」切糕 题目描述 思路分析及代码 题目分析 题解及代码 「题解」「HNOI2013」切糕 题目描述 点这里 思路分析及代码 题目分析 这道题的题目可以说得上是史上最 ...

  3. 「题解」JOIOI 王国

    「题解」JOIOI 王国 题目描述 考场思考 正解 题目描述 点这里 考场思考 因为时间不太够了,直接一上来就着手暴力.但是本人太菜,居然暴力爆 000 ,然后当场自闭- 一气之下,发现对 60pts ...

  4. 「题解」:[loj2763][JOI2013]现代豪宅

    问题 A: 现代豪宅 时间限制: 1 Sec  内存限制: 256 MB 题面 题目描述 (题目译自 $JOI 2013 Final T3$「現代的な屋敷」) 你在某个很大的豪宅里迷路了.这个豪宅由东 ...

  5. 「题解」:$Simple$

    问题 A: $Simple$ 时间限制: 1 Sec  内存限制: 256 MB 题面 题面谢绝公开. 题解 不算数学的数学题?? 直接枚举会重.$60%$两种算法:1.无脑$vis$数组记录.2.$ ...

  6. 「题解」CF1468M Similar Sets

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

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

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

  8. 「题解」NWRRC2017 Grand Test

    本文将同步发布于: 洛谷博客: csdn: 博客园: 简书. 题目 题目链接:洛谷 P7025.gym101612G. 题意概述 给你一张有 \(n\) 个点 \(m\) 条边的无向图,无重边无自环, ...

  9. 「题解」:$Six$

    问题 A: Six 时间限制: 1 Sec  内存限制: 512 MB 题面 题面谢绝公开. 题解 来写一篇正经的题解. 每一个数对于答案的贡献与数本身无关,只与它包含了哪几个质因数有关. 所以考虑二 ...

随机推荐

  1. IOS Widget(4-1):创建可配置小组件(静态配置数据)

    引言   经过前面几篇文章阅读,已经掌握开发一款小组件的基本技能了,接下来开始掌握一些相对高级一点的技能.本文创建一个可配置小组件,通过修改时间类型,让Text空间显示不同格式的时间. 本文大纲 添加 ...

  2. 十进制转n进制

    #include <stdio.h> #include <stdlib.h> #define OK 1 #define ERROR 0 #define TRUE 1 #defi ...

  3. java 运用Cipher加密再解密后会变乱码。解决方案!

    同样的方法类用main调用加解密都正常,就是当用到业务就是加密后再解密变乱码. 后来发现同样的内容加密后的内容竟不相同. 经调试发现 encryptData.getBytes() 转为字节是的使用 C ...

  4. Vue3能不能用到生产环境?

    最近,有不少朋友问我:"十三,看你写了几个Vue3的项目,你觉得Vue3能用到生产环境了吗?"结合自己的想法和尤大直播说的话,给一点建议. 别问我!没结果,除非花手摇过我. 我不是 ...

  5. 一文读懂 SuperEdge 云边隧道

    作者 李腾飞,腾讯容器技术研发工程师,腾讯云TKE后台研发,SuperEdge核心开发成员. 杜杨浩,腾讯云高级工程师,热衷于开源.容器和Kubernetes.目前主要从事镜像仓库,Kubernete ...

  6. 如何用Vim搭建IDE?

    推荐:http://harttle.com/2015/07/18/vim-cpp.html 转自:http://harttle.com/2015/11/04/vim-ide.html 一年前我从Vim ...

  7. [Django框架之视图层]

    [Django框架之视图层] 视图层 Django视图层, 视图就是Django项目下的views.py文件,它的内部是一系列的函数或者是类,用来专门处理客户端访问请求后处理请求并且返回相应的数据,相 ...

  8. ==与equals比较

    提到==与equals的区别,这就必须先回顾一下jvm内存的分配机制 ==和equals无非比较两个基本数据类型或者对象类型 八种基本类型: 基本类型 大小 默认值 封装类 byte 1 0 Byte ...

  9. centos7安装powershell和powercli

    poershell github https://github.com/PowerShell/PowerShell/releases 本次采用github下载对应的rpm进行安装 windows下安装 ...

  10. 【转载】在python的class中的,self到底是什么?

    在python的class中的,self到底是什么?   答案:self可以理解为一个字典变量,内部存的就是对象的数据属性.如:{'name':'zhang','age':'18'}就是这些. 注意只 ...