2018.09.27【Codeforces1045F】Shady Lady(凸包)

传送门


解析:

DZYO的带领下做了这道题,期间一直被 d i s s diss diss,最后几乎是照着代码抄了一遍才过。。。

这道题不知道有没有人看完题去打个了 F F T FFT FFT,反正我不会 F F T FFT FFT

思路:

这道题真的难以想象是凸包。

我们先回到原问题,大意就是给你一个 n n n项式,每项都有两个变量 x , y x,y x,y,给出的数据表示这一项 x , y x,y x,y各自的次数。
一个叫 B o r n a Borna Borna的人要给每一项填上一个系数,然后一个叫 A n i Ani Ani的淘气孩子要删去某一项。 B o r n a Borna Borna希望最后得到的多项式值域有下界,而 A n i Ani Ani希望没有下界。问最后谁的目的能达成。

可以去看一下 D Z Y O DZYO DZYO的题解,%%%。

这道题可以非常巧妙的转化成一道计算几何。
如果一个这种多项式无下界,那么将它每一项 x , y x,y x,y的次数 a , b a,b a,b转换成平面上的点 ( p , q ) (p,q) (p,q),然后做凸包,如果凸包上没有任何一个点的任何坐标是奇数。那么这个多项式是有下界的。

证明请见 D Z Y O DZYO DZYO的博客,我这里放一个本人口胡(请感性理解 )。

首先凸包内的点可以用凸包上的点向量线性组合得到。这个结论请自行学习线性空间。

对应的,所有凸包的对应的多项式的项都可以转移到其他项上面去,所以对答案有影响的只有凸包上的。(这里是真的口胡,毫无严谨性可言的,但是便于理解)

而凸包上只有偶数点的时候,我们有 J e n s e n Jensen Jensen不等式推一下加权几何平均数和加权算术平均数的关系可以得到
在这里插入图片描述
官方题解盗来的图,
其中 P P P是凸包上的点集, α \alpha α是权重,保证 0 ≤ α 0\leq \alpha 0α,且 ∑ α = 1 \sum\alpha=1 α=1

x , y x,y x,y取极大极小值的时候,它都是趋向向正无穷。

而奇点的讨论,就是如下从DZYO博客上~~(盗)~~借来的图。
在这里插入图片描述

而考虑删去一个点对凸包只会有局部影响,所以我们可以交错着删除点再做两次凸包,如果某一次凸包上出现了奇点,那么 A n i Ani Ani就有办法使得最后的多项式无下界。


代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
inline
ll getint(){
	re ll num;
	re char c;
	while(!isdigit(c=gc()));num=c^48;
	while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48);
	return num;
}

cs int N=200005;
struct Point{
	int x,y,id;
	Point():x(0),y(0),id(0){}
	Point(int x,int y,int id=0):x(x),y(y),id(id){}
	
	Point operator+(cs Point &b)cs{
		return Point(x+b.x,y+b.y);
	}
	
	Point operator-(cs Point &b)cs{
		return Point(x-b.x,y-b.y);
	}
	
	ll dot()cs{return 1ll*x*x+1ll*y*y;}
	
	friend ll cross(cs Point &a,cs Point &b){
		return 1ll*a.x*b.y-1ll*b.x*a.y;
	}
	
	bool odd()cs{return (x&1)||(y&1);}
}q[N],p[N],c[N];

inline
bool cmp(cs Point &a,cs Point &b){
	return a.x==b.x?a.y==b.y?a.id<b.id:a.y<a.y:a.x<b.x;
}

inline
bool cmp2(cs Point &a,cs Point &b){
	return cross(a-q[1],b-q[1])!=0?cross(a-q[1],b-q[1])>=0:(a-q[1]).dot()<(b-q[1]).dot();
}

int m,qn;
bool convex_hull(int n){
	sort(q+1,q+n+1,cmp);
	sort(q+2,q+n+1,cmp2);
	c[m=1]=q[1];
	for(int re i=2;i<=n;++i){
		while(m>=2&&cross(q[i]-c[m-1],c[m]-c[m-1])>=0)--m;
		c[++m]=q[i];
	}
	for(int re i=1;i<=m;++i)if(c[i].odd())return false;
	return true;
}

int col[N];
int n;
signed main(){
	n=getint()+1;q[1]=p[1]=Point(0,0,1);
	for(int re i=2;i<=n;++i){
		int x=getint(),y=getint();
		q[i]=p[i]=Point(x,y,i);
	}
	if(!convex_hull(n)){
		puts("Ani");
		return 0;
	}
	for(int re i=2;i<=m;++i)
	col[c[i].id]=(i&1)?1:2;
	
	qn=0;
	for(int re i=1;i<=n;++i){
		if(col[i]!=1)q[++qn]=p[i];
	}
	if(!convex_hull(qn)){
		puts("Ani");
		return 0;
	}
	qn=0;
	for(int re i=1;i<=n;++i){
		if(col[i]!=2)q[++qn]=p[i];
	}
	if(!convex_hull(qn)){
		puts("Ani");
		return 0;
	}
	puts("Borna");
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值