[BalticOI 2020 Day1] 混合调料

题面

link

​ 给定\(S,P,G\),之后有Q次操作,每次操作往集合S中加入一种元素\(\{S_i,P_i,G_i\}\),或删除一种元素。每次操作之后需要从S中选出\(T\subseteq S\),且\(|T|\)最小,且存在一个实数数组\(A(A_i>0)\)使

\[\sum_{i=1}^{|T|} S_iA_i=S\;\;\;\sum_{i=1}^{|T|} P_iA_i=P\;\;\; \sum_{i=1}^{|T|} G_iA_i=G \]

题解

​ 只能强行引入了。

​ 设\(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重载运算符的方法。
posted @ 2022-02-17 17:56  qwq_123  阅读(43)  评论(0编辑  收藏  举报