zoukankan      html  css  js  c++  java
  • [SCOI2016]妖怪(另类nlogn做法)

    题意

    题意

    做法

    前两种做法参考博客:https://www.luogu.com.cn/blog/ChenXingLing/solution-p3291

    这里就不再赘述,不过需要提一下,第二种做法感觉有点问题的地方是:(k)应该在([k2,k1])范围内。(当然,仅仅个人观点,不一定正确)

    然后我自己手艹出一个做法?

    首先,已知对于((a,b)),可以化作((1,frac{b}{a}))的形式,不妨化为:((1,k)),这样,就顺利的化成了一个元的形式了。

    那么对于一只妖怪,其战斗力函数为:(a+b+ak+frac{b}{k})

    不难发现,如果对于两个妖怪:(a_{1}≤a_2,b_1≤b_2)那么第一个妖怪绝对没有第二个妖怪好,此时,自动把第一个妖怪舍弃,然后再对于(a)进行升序排序,这样,妖怪就是(a)值递增,(b)值递减了。

    考虑第一个妖怪在哪个大于第二个妖怪:
    (a'=a_{1}-a_{2},b'=b_{1}-b_{2})
    那么不等式方程则为:
    (a'k+frac{b'}{k}+a'+b'≥0)
    (a'k^2+(a'+b')k+b'≥0)
    (k∈[-1,0)∩(0,-frac{b'}{a'}]),由于(k>0),所以(k∈(0,-frac{b'}{a'}])

    也就是说,第一个妖怪在这个区间都比第二个区间好。

    那么只要我们能够找到这些妖怪各自的最强的区间,然后对他们的函数在他们区间中的最小值取最小值即可。

    但是如何证明一个函数的(k)存在一个取值区间这个函数值大于其他的函数值呢?

    再次证明一个东西:(frac{b_1-b_2}{a_1-a_2}>frac{b_1-b_3}{a_1-a_3})可以推导出:(frac{b_2-b_3}{a_2-a_3}<frac{b_{1}-b_2}{a_1-a_2})
    证明过程就是交叉相乘,后面发现两条式子可以化成一条式子,那么这条式子说明了什么了?下面设(A_i)为第一个函数,(jd())为交点,说明(jd(A_1,A_3)<jd(A_1,A_2)),那么(jd(A_2,A_3)<jd(A_1,A_2)),简单来说就是(A_2)(k)不可能存在一个取值区间使得这个函数值大于其他函数值。

    同理,只要用栈维护每个函数,弹出时判断与(A_1)的交点即可,然后(A_i)(k)的取值区间则在:[(jd(A_{i-1},A_i)),(jd(A_{i},A_{i+1}))]范围内。

    至于函数的最小值,额,直接均值不等式,这个不再多讲了。

    时间复杂度:(O(nlogn))

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define  N  1100000
    using  namespace  std;
    template<class  T>
    inline  T  mymin(T  x,T  y){return  x<y?x:y;}
    template<class  T>
    inline  T  mymax(T  x,T  y){return  x>y?x:y;}
    int  n;
    struct  node
    {
    	double  a,b;
    	node(double  x=0,double  y=0){a=x;b=y;}
    }a[N],b[N];int  m;
    inline  node  operator-(node  x,node  y){return  node(x.a-y.a,x.b-y.b);}
    inline  double  jd(node  x)//求交点
    {
    	return  -x.b/x.a;//(x.a)k^2+(x.a+x.b)k+x.b   k=-x.b/x.a(其中x.a<0,x.b>0)
    }
    inline  double  getval(node  x,double  k){return  x.a+x.b+x.a*k+x.b/k;}
    inline  double  mmin(node  x,double  l,double  r)
    {
    	double  minx=sqrt(x.b/x.a),ans;//最小的数字 
    	if(l<=minx  &&  minx<=r  ||  (l<=minx  &&  r<0))ans=minx;
    	else  if(minx<l)ans=l;
    	else  ans=r;
    	return  getval(x,ans);
    }
    inline  bool  cmp(node  x,node  y){return  x.a==y.a?x.b>y.b:x.a<y.a;}
    int  main()
    {
    	scanf("%d",&n);
    	for(int  i=1;i<=n;i++)scanf("%lf%lf",&a[i].a,&a[i].b);
    	sort(a+1,a+n+1,cmp);
    	int  now=a[1].a;
    	b[m=1]=a[1];
    	for(int  i=2;i<=n;i++)
    	{
    		if(a[i].a!=now)
    		{
    			now=a[i].a;
    			while(m  &&  b[m].b<=a[i].b)m--;//维护a单调递增,b单调递减
    			while(m>1  &&  jd(b[1]-b[m])>=jd(b[1]-a[i]))m--;
    			b[++m]=a[i];
    		}
    	}
    	if(m==1)printf("%.4lf
    ",getval(b[1],sqrt(b[1].b/b[1].a)));
    	else
    	{
    		double  ans=mymin(mmin(b[1],-1,jd(b[1]-b[2])),mmin(b[m],jd(b[m-1]-b[m]),-1));
    		for(int  i=2;i<m;i++)ans=mymin(mmin(b[i],jd(b[i-1]-b[i]),jd(b[i]-b[i+1])),ans);
    		printf("%.4lf
    ",ans);
    	}
    	return  0;
    }
    
  • 相关阅读:
    洛谷P1330 封锁阳光大学
    洛谷P1341 无序字母对
    Bzoj1059 [ZJOI2007]矩阵游戏
    POJ2337 Catenyms
    Bzoj2342 [Shoi2011]双倍回文
    Bzoj1009 [HNOI2008]GT考试
    Bzoj3670 [Noi2014]动物园
    POJ2406 Power Strings
    POJ 2752 Seek the Name, Seek the Fame
    POJ3522 Slim Span
  • 原文地址:https://www.cnblogs.com/zhangjianjunab/p/13915006.html
Copyright © 2011-2022 走看看