「BalticOI 2020」混合物

「BalticOI 2020」混合物

题目大意:

对于给定的向量\(\vec{O}=(x,y,z)\)

动态维护一个集合\(S=\{(x_i,y_i,z_i)\}\)

求出最少用几个\(S\)中的元素能够 实数正系数 线性组合得到\(O\)

考虑令\(\displaystyle x'=\frac{x}{x+y+z},y'=\frac{y}{x+y+z}\),显然\(x,y\)能够完成组合,\(z\)就一定成立

此时,问题转化为了一个平面问题,答案分为几种情况

1.\(S\)包含\(O\),答案显然为1

2.\(O\)\(S\)中两点构成的线段上,显然答案为2

3.\(O\)被某一个三角形包含,答案为3

4.无解

不妨令\(T=\{P-O|P\in S\}\),此时

情况1即\(T\)包含原点

情况2即\(T\)中某两点与原点共线且在原点两端

情况3即\(S\)构成的凸包包含原点

因为只需要判断是否包含,所以其实和凸包并没有关系

考虑不包含的情况,则显然可以用一个 以原点为界的半平面 包住\(S\)中的所有点

因此可以维护每个点的极角,判断是否可以用半平面完全包含

实现上,完全包含可以认为是\(\max-\min<\pi\)

或者是半平面跨过极角为\(0\)的位置,此时令\(x,y\)分别为\(<\pi\)最大值,\(>\pi\)最小值

能包含即\(x+2\pi-y<\pi\)

#include<bits/stdc++.h>
using namespace std;
typedef long double db;
#define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i)
#define drep(i,a,b) for(int i=a,i##end=b;i>=i##end;--i)

char IO;
template <class T=int> T rd(){
	T s=0; int f=0;
	while(!isdigit(IO=getchar())) f|=IO=='-';
	do s=(s<<1)+(s<<3)+(IO^'0');
	while(isdigit(IO=getchar()));
	return f?-s:s;
}

const int N=2e5+10,INF=1e9+10;
const db eps=1e-9,PI=acos((db)-1);

int n;
struct Node{
	db x,y;
	Node(){}
	Node(db x,db y):x(x),y(y){}
	Node operator - (const Node &t) const { return Node(x-t.x,y-t.y); }
	db angle(){ 
		db t=atan2(y,x);
		if(t<-eps) t+=2*PI;
		return t;
	}
} O,A[N];
Node Read() {
	db a=rd(),b=rd(),c=rd(),s=a+b+c;
	return Node(a/s,b/s);
}

int cnt1,cnt2;
char op[2];
struct cmp{ bool operator () (const db &x,const db &y) const { return x+eps<y; } };
multiset <db,cmp> st;
db Go(db x){
	x+=PI;
	if(x>=2*PI) x-=2*PI;
	return x;
}
void Ins(Node x){
	if(fabs(x.x)<eps && fabs(x.y)<eps) return void(cnt1++);
	db y=x.angle();
	if(st.find(y)==st.end() && st.find(Go(y))!=st.end()) cnt2++;
	st.insert(y);
}

void Del(Node x){
	if(fabs(x.x)<eps && fabs(x.y)<eps) return void(cnt1--);
	db y=x.angle();
	st.erase(st.find(y));
	if(st.find(y)==st.end() && st.find(Go(y))!=st.end()) cnt2--;
}

int main(){
	O=Read();
	rep(_,1,rd()) {
		scanf("%s",op);
		if(*op=='A') Ins(A[++n]=(Read()-O));
		else Del(A[rd()]);
		if(cnt1) puts("1");
		else if(cnt2) puts("2");
		else {
			int f=1;
			if(st.empty()) f=0;
			else {
				if(*st.rbegin()-*st.begin()<PI+eps) f=0;
				else {
					auto y=st.upper_bound(PI),x=y; x--;
					if(*x+2*PI-*y<PI+eps) f=0;
				} 
			}
			puts(f?"3":"0");
		} 
	}
}
posted @ 2021-03-09 11:07  chasedeath  阅读(173)  评论(0编辑  收藏  举报