WA 最后一个点求调(有注释)
查看原帖
WA 最后一个点求调(有注释)
881015
Resstifnurvˆwˆ.tar.gz楼主2024/6/6 15:27

采用的做法是 AtCoder 上的官方题解思路。

实际上,eps 设为 [10−13,10−12][10^{-13},10^{-12}] 的时候才是 WA On #91,而 eps 设为 [10−20,10−14][10^{-20},10^{-14}] 的时候又成了 WA 在另外的 4 个点(#91 AC 了),所以猜测可能是因为某个细节没有特判导致的?

这个题已经做了一个上午了,差一点就能 AC,实在是不想就这么放弃

#include<iostream>
#include<algorithm>
using namespace std;
#define double long double
// #define DEBUG

inline int read(){
    int ret=0;
    char ch=' ',c=getchar();
    while(!('0'<=c&&c<='9')) ch=c,c=getchar();
    while('0'<=c&&c<='9') ret=ret*10+(c^48),c=getchar();
    return ch=='-'?-ret:ret;
}

const double INF=0x3f3f3f3f3f3f3f3f;
const double eps=(double)(1e-4)*(double)(1e-4)*(double)(1e-5)*(double)(1e-5);
inline bool _less(double x,double y){ return y-x>eps; }
inline bool _great(double x,double y){ return x-y>eps; }
inline bool _le(double x,double y){ return !_great(x,y); }
inline bool _ge(double x,double y){ return !_less(x,y); }
inline bool _equal(double x,double y){ return _le(x,y)&&_ge(x,y); }
struct pdd{
    double first,second;
    pdd(){}
    pdd(double x,double y){ first=x,second=y; }
    friend bool operator< (pdd &a,pdd &b){
        if(!_equal(a.first,b.first)) return _less(a.first,b.first);
        return _less(a.second,b.second);
    }
    friend bool operator== (pdd &a,pdd &b){
        if(!_equal(a.first,b.first)) return false;
        if(!_equal(a.second,b.second)) return false;
        return true;
    }
    friend bool operator> (pdd &a,pdd &b){
        if(!_equal(a.first,b.first)) return _great(a.first,b.first);
        return _great(a.second,b.second);
    }
};
// 各种重载

inline bool is_counter_clockwise(pdd &vec_a,pdd &vec_b){
    return _less(vec_a.first*vec_b.second,vec_b.first*vec_a.second);
}
// 判断向量 b 是否在向量 a 的逆时针方向

inline bool not_convex_hull(pdd &s,pdd &t,pdd &x){
    pdd vec_a=pdd(x.first-s.first,x.second-s.second);
    pdd vec_b=pdd(x.first-t.first,x.second-t.second);
    return is_counter_clockwise(vec_a,vec_b);
}
// Andrew 算法判凸壳

inline pdd get_line(pdd &a,pdd &b){
    if(_equal(a.first,b.first)) return pdd(INF,a.first);
    double K=(b.second-a.second)/(b.first-a.first);
    double B=a.second-K*a.first;
    return pdd(K,B);
}
// 获取直线方程

inline pdd get_cross(pdd &a,pdd &b,double K){
    pdd line=get_line(a,b);
    if(_ge(line.first,INF)){
        double Y=K*line.second;
        return pdd(line.second,Y);
    }
    if(_equal(line.first,K)){
        if(_equal(line.second,0.00)) return a;
        return pdd(INF,INF);
    }
    double X=line.second/(K-line.first);
    double Y=line.first*X+line.second;
    return pdd(X,Y);
}
// 获取直线与查询(相当于一条 y=kx 的直线)直线的交点

inline bool is_cross(pdd &a,pdd &b,double K){
    #ifdef DEBUG
    printf("crossing (%.2Lf,%.2Lf)->(%.2Lf,%.2Lf) with y=%.2Lf*x",a.first,a.second,b.first,b.second,K);
    #endif
    pdd cross_pt=get_cross(a,b,K);
    double L=a.first,R=b.first;
    return (_le(L,cross_pt.first)&&_le(cross_pt.first,R));
}
// 判断是否相交在线段上

int n,Q;
const int N=4e5+10;
pdd pos[N];

int _stk[N<<1],tt=0;
inline void push(int x){
    #ifdef DEBUG
    printf("push(%d)\n",x);
    #endif
    _stk[++tt]=x;
}
inline void pop(){
    #ifdef DEBUG
    printf("pop(%d)\n",_stk[tt]);
    #endif
    tt--;
}
#define stk(x) pos[_stk[x]]
void andrew(int bg){
    tt=0;
    push(bg),push(bg+1);
    for(int i=bg+2;i<=n;i++){
        while(tt>=2&&not_convex_hull(stk(tt-1),stk(tt),pos[i])) pop();
        push(i);
    }
    /*
    push(n-1);
    int hh=tt;
    for(int i=n-2;i>=1;i--){
        while(tt>=hh&&not_convex_hull(stk(tt-1),stk(tt),pos[i])) tt--;
        push(i);
    }
    */
   // 这里只用求下凸包
}

int main(){
    double mi_k=INF;
    int mi_id=0;
    double ma_x=0,ma_y=0;
    n=read();
    double x,y;
    for(int i=1;i<=n;i++){
        x=read(),y=read();
        pos[i]=pdd(y,x);
        if(_less(ma_x,y)){
            ma_x=y;
            ma_y=x;
        }
        else if(_equal(ma_x,y)){
            if(_great(ma_y,x)) ma_y=x;
        }
    }
   // 更新时间最优点
  
    sort(pos+1,pos+1+n);
    n=unique(pos+1,pos+1+n)-(pos+1);
    for(int i=1;i<=n;i++){
        y=pos[i].first,x=pos[i].second;
        if(_great(mi_k,x/y)){
            mi_k=x/y;
            mi_id=i;
        }
    }
   // 更新效率最优点(耗能最少)

    if(mi_id==n){
        double sta=pos[n].second/pos[n].first;
        Q=read();
        while(Q--){
            x=read(),y=read();
            if(_less(x/y,sta)) puts("-1");
            else printf("%.16Lf\n",y/pos[n].first);
        }
        return 0;
    }
   // 特判只有一个点的情况
    andrew(mi_id);
    /*
    if(mi_id+1==n){
        if(pos[1]>pos[2]) swap(pos[1],pos[2]);
        Q=read();
        while(Q--){
            x=read(),y=read();
            if(x/y<mi_k){
                puts("-1");
                continue;
            }
            if(x/y>=(ma_y/ma_x)){
                printf("%.10Lf\n",y/ma_x);
                continue;
            }
            pdd cross_pt=get_cross(pos[1],pos[2],x/y);
            printf("%.10Lf\n",y/cross_pt.first);
        }
        return 0;
    }
    */

    #ifdef DEBUG
    for(int i=1;i<=tt;i++) printf("%d ",_stk[i]);
    printf("\n");
    #endif

    Q=read();
    while(Q--){
        x=read(),y=read();
        double K=x/y;
        if(_less(K,mi_k)){
            puts("-1");
            continue;
        }
        if(_ge(K,ma_y/ma_x)){
            printf("%.16Lf\n",y/ma_x);
            continue;
        }
        int l=2,r=tt,mid;
        while(l<r){
            mid=(l+r)>>1;
            if(is_cross(stk(1),stk(mid),K)) r=mid;
            else l=mid+1;
        }
        #ifdef DEBUG
        printf("=== l=%d\n",l);
        #endif
        pdd cross_pt=get_cross(stk(l-1),stk(l),K);
        printf("%.16Lf\n",y/cross_pt.first);
    }
    return 0;
}

2024/6/6 15:27
加载中...