「JSOI2018」战争
「JSOI2018」战争
解题思路
我们需要每次求给一个凸包加上一个向量后是否与另外一个凸包相交,也就是说是否存在
\]
这里 \(A, B\) 表示凸包内部的点集,可以转化一步变成
\]
那相当于对 \(A,(-B)\) 作闵可夫斯基和,判断 \(w\) 是否在新的凸包内部,把新的凸包划分成三角区域,让 \(w\) 和原点做一条向量,二分一下在哪个区域然后判断一下在区域内部还是外部就可以了,复杂度 \(\mathcal O(n \log n)\) 。
code
/*program by mangoyang*/
#include<bits/stdc++.h>
#define inf (0x7f7f7f7f)
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template <class T>
inline void read(T &x){
int ch = 0, f = 0; x = 0;
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
if(f) x = -x;
}
const int N = 1000005;
struct P{
ll x, y;
friend P operator + (P a, P b){ return (P){a.x + b.x, a.y + b.y}; }
friend P operator - (P a, P b){ return (P){a.x - b.x, a.y - b.y}; }
friend ll operator * (P a, P b){ return a.x * b.y - b.x * a.y; }
inline ll dis(){ return x * x + y * y; }
}A[N], B[N], C[N], s1[N], s2[N], st[N], O;
int n, m, q;
inline bool cmp1 (P A, P B){
return A.y != B.y ? A.y < B.y : A.x < B.x;
}
inline bool cmp2 (P A, P B){
//叉积一样按照离原点距离排,防止较远的点被近的点日掉
ll res = (A - O) * (B - O);
return res ? res > 0 : (A - O).dis() < (B - O).dis();
}
inline int convex(P *A, int len){
//求点集 A 的凸包并返回凸包大小
sort(A + 1, A + len + 1, cmp1); O = A[1];
sort(A + 2, A + len + 1, cmp2);
int top = 1; st[top] = A[1];
for(int i = 2; i <= len; i++){
while(top > 1 && (st[top] - st[top-1]) * (A[i] - st[top-1]) <= 0) top--;
st[++top] = A[i];
}
for(int i = 1; i <= top; i++) A[i] = st[i];
return top;
}
inline int inconvex(P x, P *A, int len){
//判断点 x 是否在大小为len的凸包 A 里,二分找到向量所在的三角区域
O = A[1];
if((x - O) * (A[2] - O) > 0 || (x - O) * (A[len] - O) < 0) return 0;
int pos = lower_bound(A + 2, A + len + 1, x, cmp2) - A - 1;
return (x - A[pos]) * (A[pos%len+1] - A[pos]) <= 0;
}
inline int Minkowski(P *A, P *B, P *C, int n, int m){
//将大小为 n, m 的凸包 A, B 的闵可夫斯基和存在 C 中,并返回凸包大小
int tot1 = 0, tot2 = 0;
for(int i = 1; i < n; i++) s1[++tot1] = A[i+1] - A[i];
s1[++tot1] = A[1] - A[n];
for(int i = 1; i < m; i++) s2[++tot2] = B[i+1] - B[i];
s2[++tot2] = B[1] - B[m];
int p1 = 1, p2 = 1, tot = 1; C[tot] = A[1] + B[1];
for(; p1 <= n && p2 <= m; tot++)
C[tot+1] = C[tot] + (s1[p1] * s2[p2] >= 0 ? s1[p1++] : s2[p2++]);
for(; p1 <= n; p1++, tot++) C[tot+1] = C[tot] + s1[p1];
for(; p2 <= m; p2++, tot++) C[tot+1] = C[tot] + s2[p2];
return tot = convex(C, tot);
}
int main(){
read(n), read(m), read(q);
for(int i = 1; i <= n; i++) read(A[i].x), read(A[i].y);
n = convex(A, n);
for(int i = 1; i <= m; i++)
read(B[i].x), read(B[i].y), B[i].x = -B[i].x, B[i].y = -B[i].y;
m = convex(B, m);
int len = Minkowski(A, B, C, n, m);
while(q--){
ll x, y; read(x), read(y);
printf("%d\n", inconvex((P){x, y}, C, len));
}
return 0;
}
「JSOI2018」战争的更多相关文章
- 【LOJ】#2549. 「JSOI2018」战争
题解 仔细分析了一下,如果写个凸包+每次暴力半平面交可以得到70分,正解有点懵啊 然后用到了一个非常结论,但是大概出题人觉得江苏神仙一个个都可以手证的结论吧.. Minkowski sum 两个凸包分 ...
- 「JLOI2015」战争调度 解题报告
「JLOI2015」战争调度 感觉一到晚上大脑就宕机了... 题目本身不难,就算没接触过想想也是可以想到的 这个满二叉树的深度很浅啊,每个点只会和它的\(n-1\)个祖先匹配啊 于是可以暴力枚举祖先链 ...
- 「JLOI2015」战争调度
题目 [内存限制:256 MiB][时间限制:1000 ms] [标准输入输出][题目类型:传统][评测方式:文本比较] 题目描述 脸哥最近来到了一个神奇的王国,王国里的公民每个公民有两个下属或者没有 ...
- LOJ 2550 「JSOI2018」机器人——找规律+DP
题目:https://loj.ac/problem/2550 只会写20分的搜索…… #include<cstdio> #include<cstring> #include&l ...
- LOJ 2548 「JSOI2018」绝地反击 ——二分图匹配+网络流手动退流
题目:https://loj.ac/problem/2548 如果知道正多边形的顶点,就是二分答案.二分图匹配.于是写了个暴力枚举多边形顶点的,还很愚蠢地把第一个顶点枚举到 2*pi ,其实只要 \( ...
- LOJ 2551 「JSOI2018」列队——主席树+二分
题目:https://loj.ac/problem/2551 答案是排序后依次走到 K ~ K+r-l . 想维护一个区间排序后的结果,使得可以在上面二分.求和:二分可以知道贡献是正还是负. 于是想用 ...
- LOJ 2547 「JSOI2018」防御网络——思路+环DP
题目:https://loj.ac/problem/2547 一条树边 cr->v 会被计算 ( n-siz[v] ) * siz[v] 次.一条环边会被计算几次呢?于是去写了斯坦纳树. #in ...
- LOJ #2547 Luogu P4517「JSOI2018」防御网络
好像也没那么难写 LOJ #2547 Luogu P4517 题意 在一棵点仙人掌中等概率选择一个点集 求选出点集的斯坦纳树大小的期望 定义点仙人掌为不存在一个点在多个简单环中的连通图 斯坦纳树为在原 ...
- LOJ 2546 「JSOI2018」潜入行动——树形DP
题目:https://loj.ac/problem/2546 dp[ i ][ j ][ 0/1 ][ 0/1 ] 表示 i 子树,用 j 个点,是否用 i , i 是否被覆盖. 注意 s1<= ...
随机推荐
- curator框架的使用以及实现分布式锁等应用与zkclient操作zookeeper,简化复杂原生API
打开zookeeper集群 先体会一下原生API有多麻烦(可略过): //地址 static final String ADDR = "192.168.171.128:2181,192.16 ...
- java中并发Queue种类与各自API特点以及使用场景!
一 先说下队列 队列是一种数据结构.它有两个基本操作:在队列尾部加入一个元素,和从队列头部移除一个元素(注意不要弄混队列的头部和尾部) 就是说,队列以一种先进先出的方式管理数据,如果你试图向一个 已经 ...
- Linux下C程序的反汇编【转】
转自:http://blog.csdn.net/u011192270/article/details/50224267 前言:本文主要介绍几种反汇编的方法. gcc gcc的完整编译过程大致为:预处理 ...
- python并发爬虫利器tomorrow(一)
tomorrow是我最近在用的一个爬虫利器,该模块属于第三方的一个模块,使用起来非常的方便,只需要用其中的threads方法作为装饰器去修饰一个普通的函数,既可以达到并发的效果,本篇将用实例来展示to ...
- 一、Vue入门
vue官网:https://cn.vuejs.org/ 学习路线:VueJs2.0建议学习路线 在浏览器上安装 Vue Devtools工具 1.vue入门 <script src=" ...
- python网络编程--线程event
一:线程event作用 Python提供了Event对象用于线程间通信,它是线程设置的信号标志,如果信号标志位真,则其他线程等待直到信号结束. Event对象实现了简单的线程通信机制,它提供了设置信号 ...
- JS动态创建元素(两种方法)
前言 创建元素有两种方法 1)将需要创建的元素,以字符串的形式拼接:找到父级元素,直接对父级元素的innnerHTML进行赋值. 2)使用Document.Element对象自带的一些函数,来实现动态 ...
- LCT解读(1)
蒟蒻的LCT解读(1) 前段时间本蒟蒻自学了一下LCT,但是网上的很多资料并不很全,而且作为一个数组选手,我看指针代码真的很麻烦,所以就在这里写一篇数组选手能看懂的代码. LCT的初步了解 LCT全称 ...
- wpf 查找 子元素
RightContainer.ApplyTemplate();//如果找不到,就执行该句试一试 var xxx=UIHelper.FindChild<ScrollViewer>(Right ...
- HDU 4632 Palindrome subsequence(区间DP求回文子序列数)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4632 题目大意:给你若干个字符串,回答每个字符串有多少个回文子序列(可以不连续的子串).解题思路: 设 ...