[BalticOI 2020 Day1] 混合调料
题面
link
给定\(S,P,G\),之后有Q次操作,每次操作往集合S中加入一种元素\(\{S_i,P_i,G_i\}\),或删除一种元素。每次操作之后需要从S中选出\(T\subseteq S\),且\(|T|\)最小,且存在一个实数数组\(A(A_i>0)\)使
题解
只能强行引入了。
设\(x_i=\frac{S_i}{G_i},y_i=\frac{P_i}{G_i}\),相当于将所有\(G_i=1\),也就是只要保证\(\sum A_i=1\)就可以满足\(G\)的限制,但是\(G_i\)可以为\(0\),那么我们只能换一种方式,我们设\(x_i=\frac{S_i}{S_i+P_i+G_i},y_i=\frac{P_i}{S_i+P_i+G_i}\),这么操作之后,我们保证\(S_i+P_i+G_i=1\),目标状态也如此,此时我们同样可以通过需要满足的条件推导出\(\sum (S_i+P_i+G_i)A_i= S+P+G=1\),同样保证了\(\sum A_i=1\)。
这时我们可以将\((x_i,y_i)\)看作是一组元素了,当然给定的\(S,P,G\)也可以这么转化,而此时只要我们满足\(x_i\)之和为\(x\),\(y_i\)之和为\(y\),且\(\sum A_i=1\)就行。
消除掉一维之后我们可以将一个元素看成一个向量(点),想象一下,或许高中学向量的时候老师会告诉你,\(\vec c\)满足\(\lambda \vec a+(1-\lambda)\vec b(0\le\lambda \le 1)\),那么\(\vec c(x_c,y_c)\)在\(\vec a(x_a,y_a)\)和\(\vec b(x_b,y_b)\)所连成的线段上。
但是还是不好解决,因为答案点会是这个坐标系上的某一个点,那么我们就设\(x'_i=x_i-x,y_i=y_i'-y\),那么我们就只需要保证过原点就行。
所以现在总结一下所有的情况:
- 答案为1:该点就是原点。
- 答案为2:存在两个点,两个点的连线过原点。
- 答案为3:存在三个点,使第三个点经过原点对称在另外两个点的夹角的区域内。
我们将向量都转化成单位圆上的点(等比例变换),然后答案为2的就可以开一个map。
考虑答案为3的,其实就是当前集合内点按极角排序之后,两点间的最大角度\(\le \pi\)。同样可以通过单位圆上结合反三角函数解决(貌似直接y用三角函数判也是可以的)。
注意:由于精度损失,使用map的时候需要重载运算符,注意map判\(a=b\)是通过\(a \nless b\)且\(b\nless a\)来判断的,所以重载时要往不满足的方向加eps。
启发
- 通过化式子将三种元素化成两种元素。
- 记得向量的一些几何操作。
- 记得维护角度的方法。
- double用map重载运算符的方法。