「题解」USACO15FEB Fencing the Herd G
本文将同步发布于:
- 洛谷博客;
- 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,求
maxp∈S{axp+byp−c}\max_{p\in S}\{ax_p+by_p-c\}p∈Smax{axp+byp−c}
minp∈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=−bax+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=−bax+bc+min
我们发现:
- 若 b>0b>0b>0,我们只需要最小化该直线在 yyy 轴上的截距即可,维护一个下凸包,在下凸包上二分斜率求解即可;
- 若 b<0b<0b<0,我们则可以通过变号等方法修改成为 b>0b>0b>0 的情况;
- 若 b=0b=0b=0,我们发现此时的最小值必定在凸包的右端点取到,若用 min\texttt{min}min 值作为判据,则不受影响,无需考虑。
分治方法优化转移
上述方法需要动态维护两个凸包,并且凸包的横坐标不具有单调性,这需要用 平衡树 来维护。
考虑到本题并不强制在线,我们考虑离线下来,利用 cdq 分治来维护凸包,时间复杂度为 Θ(nlog2n)\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] 内直线的贡献即可。
维护凸包所需时间复杂度为排序的 Θ(nlog2n)\Theta(n\log_2n)Θ(nlog2n),结合主定理分析可知最终时间复杂度为 Θ(nlog22n)\Theta(n\log_2^2n)Θ(nlog22n)。
参考程序
更多细节参见参考程序。
#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相关推荐
- 「题解」300iq Contest 2 H. Honorable Mention
本文将同步发布于: 洛谷博客: csdn: 博客园: 简书. 题目 题目链接:gym102331H. 题意概述 给定一个长度为 n n n 的序列 a a a,有 q q q 次询问,每次询问给定三个 ...
- 「题解」蝙蝠侠的麻烦
没 事 找 事 「我的做题历程」: step1:观察题面. 「蝙蝠侠需要找到一个最长的字符串,使得这个字符串作为一个子序列被包含在所有的三个字符串中」,可以得出这是一道最长公共子序列,而且有三个字 ...
- 「题解」:[组合数学]:Perm 排列计数
题干: Description称一个1,2,-,N的排列P1,P2-,Pn是Magic的,当且仅当2<=i<=N时,Pi>Pi/2. 计算1,2,-N的排列中有多少是Magic的,答 ...
- 「题解」:[BZOJ4558]方
问题: 方 时间限制: 2 Sec 内存限制: 256 MB 题面 题目描述 上帝说,不要圆,要方,于是便有了这道题.由于我们应该方,而且最好能够尽量方,所以上帝派我们来找正方形 上帝把我们派到了一 ...
- 「题解」300iq Contest 2 B Bitwise Xor
本文将同步发布于: 洛谷博客: csdn: 博客园: 简书. 题目 题目链接:gym102331B. 题意概述 给你一个长度为 nnn 的序列 aia_iai,求一个最长的子序列满足所有子序列中的元 ...
- 「题解」:[线段树]:永无乡
题面 题目描述 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过桥可以从一个岛 ...
- 「题解」老鼠与猫的交易
题目描述 有一只老鼠很喜欢奶酪,但是奶酪被分别放在N个房间里,而且这些房间都有一只猫咪看守,现在它准和猫咪们 做个交易.它有M磅的猫食,想用这M磅猫食换取奶酪.在猫咪看守的每一个房间里有奶酪J[i]磅 ...
- 「题解」清华集训 2016 你的生命已如风中残烛
本文将同步发布于: 洛谷博客: csdn: 博客园: 简书: 题目 题目链接:洛谷 P6672.UOJ 273. 题意简述 给你牌数为 m + 1 m+1 m+1 的牌堆,其中第 m + 1 m+1 ...
- 「题解」CF1468M Similar Sets
本文将同步发布于: 洛谷博客: csdn: 博客园: 简书. 题目 题目链接:洛谷.CF1468M. 题意简述 给定 n n n 个集合 S 1 ∼ n S_{1\sim n} S1∼n,问是否存在 ...
最新文章
- Ant Design 入门-引用自己命名的组件
- springboot解决js前端跨域问题,javascript跨域问题解决
- 中国WEB 2.0的质变过程
- winform的UI设计关键属性汇总
- uci数据集_干货收藏!三大领域常用十大开源数据集
- bootstrap3 中文手册 [下载]
- Java高并发入门-线程初步
- mysql mongodb 事务_认识MongoDB 4.0的新特性——事务(Transactions)
- 【Linux使用】Centos 7设置时区与时钟(chrony / ntp /systemd)
- 红皮书--With语句及布尔型
- 链表中倒数第 k 个节点
- ffmbc——为广播电视以及专业用途量身定制的FFmpeg
- SPF邮件伪造漏洞测试脚本
- eval函数pythonmopn_pytorch:model.train和model.eval用法及区别详解
- arm-4-裸板开发
- FFmpeg 解码 H264 格式的视频
- echarts地图各种点位实现
- Microsoft Edge浏览器黑色背景修改
- 如何删除重复项只保留最新项
- 坚定文化新自信 提升文化软实力
热门文章
- 【转】红帽 Red Hat Linux相关产品iso镜像下载【迅雷快传】【百度云】【更新7.1】...
- Joomla模板安装需安装范例数据库
- Windows 10 连接 Zune 直接拷歌的方法
- 2022隐私计算十大观察
- 高中教资信息技术Flash动画软件分享
- 设计模式与软考试题之状态模式(二)
- Hyperledger技术简介
- 2021.11.17洛谷小鱼游泳进阶版——c语言
- 【历史上的今天】11 月 12 日:USB 3.0 发布;图灵机论文被发表;TinyOS 创作者诞生
- CPU、MPU、MCU、SoC、MCM介绍