这还是个被我咕了N久的玩意

Minkowski和是一个奇怪的玩意

他长这样

$S={a+b \| a \in A , b \in B}$

AB可以是点集也可是向量集(显然)

他可以处理一些奇怪的东西

比如说我们来看这个题

JSOI2018 战争

你发现它要求的就是判断向量是否存在于A-B的Minkowski和里

那么你套上板子就做完了

好了你大概了解了Minkowski和是什么

我们现在来学怎么写

我们根据直观理解 Minkowski上的点一定是点集构成的凸包上的点

于是我们暴力求出所有点再进行一次求凸包就做完了 复杂度是 O(|A|*|B|)

它看起来就不是很优 肯定可以优化

我们发现很好的性质 凸包上的点它的斜率是单调的 所以显然可以TwoPointers优化

我们直接观察哪一个在外面拓展就可以了

代码实现扔这里了

//Love and Freedom.
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#define inf 20021225
#define ll long long
#define db double
#define eps 1e-8
#define N 200010
using namespace std;
int read()
{
int f=,s=; char ch=getchar();
while(ch<''||ch>''){if(ch=='-') f=-; ch=getchar();}
while(ch>=''&&ch<='') s=s*+ch-'',ch=getchar();
return f*s;
}
struct poi
{
db x,y;
poi(){}
poi(db _x,db _y){x=_x,y=_y;}
};
typedef poi vec;
vec operator+(vec a,vec b){return vec(a.x+b.x,a.y+b.y);}
vec operator-(vec a,vec b){return vec(a.x-b.x,a.y-b.y);}
vec operator*(vec a,db b){return vec(a.x*b,a.y*b);}
vec operator/(vec a,db b){return vec(a.x/b,a.y/b);}
db cross(vec a,vec b){return a.x*b.y-a.y*b.x;}
db dot(vec a){return a.x*a.x+a.y*a.y;}
db len(vec a){return sqrt(dot(a));}
db dis(poi a,poi b){return len(b-a);}
poi p0;
int dcmp(db x){return x>eps?:x<-eps?-:;}
bool cmp(poi p1,poi p2){return dcmp(cross(p1-p0,p2-p0))==||(dcmp(cross(p1-p0,p2-p0))==&&dis(p0,p1)<dis(p0,p2));}
int gethull(poi *p,poi *h,int n)
{
p0=poi{1e18,1e18}; int id=;
for(int i=;i<=n;i++)
if(dcmp(p[i].x-p0.x)<||(dcmp(p[i].x-p0.x)==&&dcmp(p[i].y-p0.y)<))
id=i,p0=p[i];
swap(p[],p[id]); sort(p+,p+n+,cmp);
int top=; h[]=p[],h[]=p[];
for(int i=;i<=n;i++)
{
while(top>&&dcmp(cross(p[i]-h[top-],h[top]-h[top-]))>=) top--;
h[++top]=p[i];
}
return top;
}
poi A[N],B[N],p[N],C[N]; int na,nb,nc;
void minkowski()
{
A[na+]=A[],B[nb+]=B[];
C[nc=]=A[]+B[]; int i=,j=;
while(i<=na&&j<=nb)
{
vec v1=A[i+]+B[j]-C[nc],v2=A[i]+B[j+]-C[nc];
if(dcmp(cross(v1,v2))>=)
C[++nc]=A[i+]+B[j],i++;
else
C[++nc]=A[i]+B[j+],j++;
}
while(i<=na) C[++nc]=A[i]+B[j],i++;
while(j<=nb) C[++nc]=A[i]+B[j],j++;
}
bool check(poi w)
{
if((dcmp(cross(w-C[],C[nc]-C[]))==&&dis(C[nc],C[])>=dis(C[],w))||(dcmp(cross(w-C[],C[]-C[]))== && dis(C[],w)<=dis(C[],C[]))) return ;
int l=,r=nc,ans=;
while(l<=r)
{
int mid=l+r>>; poi p1=C[mid];
if(dcmp(cross(p1-C[],w-C[]))>=) l=mid+,ans=mid;
else r=mid-;
}
if(ans==nc||!ans) return ;
poi p1=C[ans],p2=C[ans+];
if(dcmp(cross(p1-w,p2-w))>=) return ;
return ;
}
int main()
{
int n1=read(),n2=read(),q=read();
for(int i=;i<=n1;i++) p[i].x=read(),p[i].y=read();
na=gethull(p,A,n1);
for(int i=;i<=n2;i++) p[i].x=-read(),p[i].y=-read();
nb=gethull(p,B,n2);
minkowski();
while(q--)
{
poi w; w.x=read(),w.y=read();
printf("%d\n",check(w));
}
return ;
}

注:1.求点是否在凸包内可以直接三角剖分以后二分在哪个极角区间内即可 2.至于为什么我想锤爆我自己的狗头呢 因为我的cmp写了dcmp>1调了一个世纪xtbl

另一道题

N校联考的题

(题面好像没法放/px)

就是我们首先猜结论 对于奇数和偶数的答案分别是凸的 那么考虑维护奇偶正负共四个凸的答案

我们分治去做 考虑如何合并

由于是凸的所以差分单调 那么我们就可以TwoPointers优化

然后求完答案继续维护差分数组

(这个玩意貌似还叫做分治max卷积/px)

发现这个过程其实也是在求Minkowski和

我的代码是展开讨论写的 于是它贼快但是贼长(

//Love and Freedom.
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#define inf (ll)(1e18)
#define ll long long
#define N 500010
using namespace std;
int read()
{
int f=,s=; char ch=getchar();
while(ch<''||ch>''){if(ch=='-') f=-; ch=getchar();}
while(ch>=''&&ch<='') s=s*+ch-'',ch=getchar();
return f*s;
}
ll f[N][],d[N][],tmp[N][],a[N];
void solve(int l,int r)
{
if(l==r){f[l][]=a[l],f[l][]=a[l]; d[l][]=a[l],d[l][]=a[l]; return;}
int mid=l+r>>; solve(l,mid); solve(mid+,r);
int it1,it2; ll val;
for(int i=;i<=r-l+;i++) tmp[i][]=-inf,tmp[i][]=inf;
it1=l+,it2=mid+; val=d[l][];
for(int i=;i<=r-l+;i+=) // odd l odd+ r even-
{
tmp[i][]=max(tmp[i][],val);
if(it2>r- && it1>mid-) break;
if(it2>r- || (it1<=mid-&&d[it1][]+d[it1+][]>-d[it2][]-d[it2+][]))
val+=d[it1][]+d[it1+][],it1+=;
else
val-=d[it2][]+d[it2+][],it2+=;
}
it1=l,it2=mid+,val=d[mid+][];// printf("%lld\n",val);
for(int i=;i<=r-l+;i+=) // odd l even+ r odd+
{
tmp[i][]=max(tmp[i][],val);
if(it2>r- && it1>mid-) break;
if(it2>r- || (it1<=mid-&&d[it1][]+d[it1+][]>d[it2][]+d[it2+][]))
val+=d[it1][]+d[it1+][],it1+=;
else
val+=d[it2][]+d[it2+][],it2+=;
}
it1=l+,it2=mid+,val=d[l][]-d[mid+][];
for(int i=;i<=r-l+;i+=) // even l odd+ r odd-
{
tmp[i][]=max(tmp[i][],val);//printf("%d %d %d %lld\n",i,it1,it2,val);// printf("%lld\n",val);
if(it2>r- && it1>mid-) break;
if(it2>r- || (it1<=mid-&&d[it1][]+d[it1+][]>-d[it2][]-d[it2+][]))
val+=d[it1][]+d[it1+][],it1+=;
else
val-=d[it2][]+d[it2+][],it2+=;
}
it1=l,it2=mid+,val=;
for(int i=;i<=r-l+;i+=) // even l even+ r even+
{
tmp[i][]=max(tmp[i][],val);
if(it2>r- && it1>mid-) break;
if(it2>r- || (it1<=mid-&&d[it1][]+d[it1+][]>d[it2][]+d[it2+][]))
val+=d[it1][]+d[it1+][],it1+=;
else
val+=d[it2][]+d[it2+][],it2+=;
} it1=l+,it2=mid+; val=d[l][];
for(int i=;i<=r-l+;i+=) // odd l odd+ r even-
{
tmp[i][]=min(tmp[i][],val);
if(it2>r- && it1>mid-) break;
if(it2>r- || (it1<=mid-&&d[it1][]+d[it1+][]<-d[it2][]-d[it2+][]))
val+=d[it1][]+d[it1+][],it1+=;
else
val-=d[it2][]+d[it2+][],it2+=;
}
it1=l,it2=mid+,val=d[mid+][];
for(int i=;i<=r-l+;i+=) // odd l even+ r odd+
{
tmp[i][]=min(tmp[i][],val);
if(it2>r- && it1>mid-) break;
if(it2>r- || (it1<=mid-&&d[it1][]+d[it1+][]<d[it2][]+d[it2+][]))
val+=d[it1][]+d[it1+][],it1+=;
else
val+=d[it2][]+d[it2+][],it2+=;
}
it1=l+,it2=mid+,val=d[l][]-d[mid+][];
for(int i=;i<=r-l+;i+=) // even l odd+ r odd-
{
tmp[i][]=min(tmp[i][],val);
if(it2>r- && it1>mid-) break;
if(it2>r- || (it1<=mid-&&d[it1][]+d[it1+][]<-d[it2][]-d[it2+][]))
val+=d[it1][]+d[it1+][],it1+=;
else
val-=d[it2][]+d[it2+][],it2+=;
}
it1=l,it2=mid+,val=;
for(int i=;i<=r-l+;i+=) // even l even+ r even+
{
tmp[i][]=min(tmp[i][],val);
if(it2>r- && it1>mid-) break;
if(it2>r- || (it1<=mid-&&d[it1][]+d[it1+][]<d[it2][]+d[it2+][]))
val+=d[it1][]+d[it1+][],it1+=;
else
val+=d[it2][]+d[it2+][],it2+=;
}
//printf("%d %d\n",l,r);
for(int i=;i<=r-l+;i++)
f[l+i-][]=tmp[i][],
f[l+i-][]=tmp[i][];
//puts("");
d[l][]=f[l][],d[l][]=f[l][];
for(int i=l+;i<=r;i++)
d[i][]=f[i][]-f[i-][],
d[i][]=f[i][]-f[i-][];
}
int main()
{
int n=read();
for(int i=;i<=n;i++) a[i]=read();
solve(,n);
for(int i=;i<=n;i++)
printf("%lld ",f[i][]);
return ;
}

【学习笔记】Minkowski和的更多相关文章

  1. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  2. PHP-自定义模板-学习笔记

    1.  开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2.  整体架构图 ...

  3. PHP-会员登录与注册例子解析-学习笔记

    1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...

  4. 2014年暑假c#学习笔记目录

    2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ...

  5. JAVA GUI编程学习笔记目录

    2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...

  6. seaJs学习笔记2 – seaJs组建库的使用

    原文地址:seaJs学习笔记2 – seaJs组建库的使用 我觉得学习新东西并不是会使用它就够了的,会使用仅仅代表你看懂了,理解了,二不代表你深入了,彻悟了它的精髓. 所以不断的学习将是源源不断. 最 ...

  7. CSS学习笔记

    CSS学习笔记 2016年12月15日整理 CSS基础 Chapter1 在console输入escape("宋体") ENTER 就会出现unicode编码 显示"%u ...

  8. HTML学习笔记

    HTML学习笔记 2016年12月15日整理 Chapter1 URL(scheme://host.domain:port/path/filename) scheme: 定义因特网服务的类型,常见的为 ...

  9. DirectX Graphics Infrastructure(DXGI):最佳范例 学习笔记

    今天要学习的这篇文章写的算是比较早的了,大概在DX11时代就写好了,当时龙书11版看得很潦草,并没有注意这篇文章,现在看12,觉得是跳不过去的一篇文章,地址如下: https://msdn.micro ...

  10. ucos实时操作系统学习笔记——任务间通信(消息)

    ucos另一种任务间通信的机制是消息(mbox),个人感觉是它是queue中只有一个信息的特殊情况,从代码中可以很清楚的看到,因为之前有关于queue的学习笔记,所以一并讲一下mbox.为什么有了qu ...

随机推荐

  1. leetcode206 反转链表 两种做法(循环,递归)

    反转链表 leetcode206 方法1 循环 public ListNode reverseList(ListNode head) { if (head == null || head.next = ...

  2. 【flask_sqlalchemy】模糊查询

    flask_sqlalchemy的查询方法有filter()和filter_() 这2个方法的主要区别如下: 模块 语法 ><(大于和小于)查询 and_和or_查询 filter_by( ...

  3. OpenStack Nova 高性能虚拟机之 NUMA 架构亲和

    目录 文章目录 目录 写在前面 计算平台体系结构 SMP 对称多处理结构 NUMA 非统一内存访问结构 MPP 大规模并行处理结构 Linux 上的 NUMA 基本对象概念 NUMA 调度策略 获取宿 ...

  4. ubuntu服务器允许Root用户登录

    1.重置root密码 sudo passwd root 2.修改ssh配置文件 sudo vim /etc/ssh/sshd_config后进入配置文件中修改PermitRootLogin后的默认值为 ...

  5. IDEA使用设置

    IDEA版本为2017.2.1 1.设置主题 File->Settings->Appearance,界面如下 2.修改快捷键-Eclipse方式 File->Settings-> ...

  6. 一文学会Go - 2 数据结构与算法实践篇

    练习:使用go语言实现冒泡排序和归并排序 冒泡排序是所有排序算法中最简单的,练习时先实现它: func bubbleSort(array []int) { n := len(array) ; j &l ...

  7. 科普:PV,UV,VV,IP

    1.PV PV即Page View,即页面浏览量或点击量,用户每一次对网站中的每个网页访问均被记录一次.用户对同一页面的多次访问,访问量累计. 2.UV UV即Unique Visitor,是指通过互 ...

  8. 【BZOJ2622】[2012国家集训队测试]深入虎穴

    虎是中国传统文化中一个独特的意象.我们既会把老虎的形象用到喜庆的节日装饰画上,也可能把它视作一种邪恶的可怕的动物,例如“武松打虎”或者“三人成虎”.“不入虎穴焉得虎子”是一个对虎的威猛的形象的极好体现 ...

  9. 无法获得锁 /var/lib/dpkg/lock-frontend - open (11: 资源暂时不可用)

    ubuntu更新软件时 apt-get upgrade 遇到 E: 无法获得锁 /: 资源暂时不可用) E: Unable to acquire the dpkg frontend lock (/va ...

  10. react-native的技巧

    按钮定制 給图片添加点击事件 <TouchableOpacity onPress={this.lookAlbum} style={{flex: 0, height: 40, width: 40, ...