初中生数学题
题意
平面上最开始只包含3个点,然后还会依次出现N个点。每新增一个点,请你求出包含这些点的周长最小的多边形的面积。
思路
采用平衡树维护,每次插入寻找前驱和后继,然后添加节点即可。
注意本题有可能会出现三点共线的情况,可以通过随机指定初始点来解决。
精度略有毒瘤之处。
代码
#include <bits/stdc++.h>
#include <cmath>
using namespace std;
namespace StandardIO {
template<typename T> inline void read (T &x) {
x=0;T f=1;char c=getchar();
for (; c<'0'||c>'9'; c=getchar()) if (c=='-') f=-1;
for (; c>='0'&&c<='9'; c=getchar()) x=x*10+c-'0';
x*=f;
}
template<typename T> inline void write (T x) {
if (x<0) putchar('-'),x=-x;
if (x>=10) write(x/10);
putchar(x%10+'0');
}
}
using namespace StandardIO;
namespace Solve {
const int N=100100;
int n;
long long ans;
struct node {
long long x,y;
long double rad;
node () {}
node (int _x,int _y):x(_x),y(_y){}
node (int _x,int _y,long double _r):x(_x),y(_y),rad(_r){}
node operator - (const node &a) {
return node(x-a.x,y-a.y);
}
node operator + (const node &a) {
return node(x+a.x,y+a.y);
}
long long operator * (const node &a) {
return (x*a.y-y*a.x);
}
} a[N],S;
long double X,Y;
set<node> sexy;
inline bool operator < (const node &x,const node &b) {
return x.rad<b.rad;
}
inline long double rad (node x) {
return (long double)atan2((x.y-S.y),(x.x-S.x));
}
inline node pre (node x) {
if (sexy.count(x)) return x;
set<node>::iterator it=sexy.lower_bound(x);
if (it==sexy.begin()) it=sexy.end();
return *(--it);
}
inline node suc (node x) {
set<node>::iterator it=sexy.upper_bound(x);
if (it==sexy.end()) it=sexy.begin();
return *it;
}
inline long long Abs (long long a) {
return (a>0)?a:-a;
}
inline long long calc (node x,node b) {
return Abs(x*b);
}
inline void insert (node x) {
if (sexy.size()<=2) {
sexy.insert(x);
return;
}
node l=pre(x),r=suc(x);
if ((x-l)*(r-l)<=0) return;
ans+=calc(x-l,r-l);
while (1) {
node tmp=pre(x);
sexy.erase(tmp),l=pre(x);
if ((x-l)*(l-tmp)>=0) {
sexy.insert(tmp);
break;
}
ans+=calc(tmp-x,l-x);
}
while (1) {
node tmp=suc(x);
sexy.erase(tmp),r=suc(x);
if ((x-r)*(r-tmp)<=0) {
sexy.insert(tmp);
break;
}
ans+=calc(tmp-x,r-x);
}
sexy.insert(x);
}
inline void init () {
long double J=(long double)1.92,Z=(long double)6.08,M=(long double)1.7;
S=node((long double)((long double)a[1].x*J+(long double)a[2].x*Z+(long double)a[3].x*M)/(long double)(J+Z+M),(long double)((long double)a[1].y*J+(long double)a[2].y*Z+(long double)a[3].y*M)/(long double)(J+Z+M));
insert(node(a[1].x,a[1].y,rad(a[1])));
insert(node(a[2].x,a[2].y,rad(a[2])));
insert(node(a[3].x,a[3].y,rad(a[3])));
ans+=calc(a[1]-a[3],a[3]-a[2]);
}
inline void MAIN () {
for (register int i=1; i<=3; ++i) read(a[i].x),read(a[i].y);
init();
read(n);
for (register int i=4; i<=n+3; ++i) {
read(a[i].x),read(a[i].y);
insert(node(a[i].x,a[i].y,rad(a[i])));
write(ans),putchar('\n');
}
}
#undef int
}
int main () {
Solve::MAIN();
}