1. 程式人生 > >正睿 2019 省選十連測 Day1 T1 終

正睿 2019 省選十連測 Day1 T1 終

把題目給出的式子化簡一下

得到i-->j的收益等於=1/2(bi(bj/aj)-bj*(bi/ai))

發現是一個f(x)g(y)-f(y)g(x)的形式

因此,這個收益等價於(bi,bi/ai),(bj,bj/aj),(0,0)三點圍成的有向三角形的面積

最大的收益顯然等價於這n個點的凸包的面積


#include<iostream>
#include<cctype>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#define N 220000
#define eps 1e-7
#define inf 1e9+7
#define ll long long
using namespace std;
inline int read()
{
    char ch=0;
    int x=0,flag=1;
    while(!isdigit(ch)){ch=getchar();if(ch=='-')flag=-1;}
    while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return x*flag;
}
int dcmp(double x)
{
    if(fabs(x)<=eps)return 0;
    return x>0?+1:-1;
}
struct Point
{
    double x,y;
}p[N];
typedef Point Vector;
Vector operator+(Vector a,Vector b){return (Vector){a.x+b.x,a.y+b.y};}
Vector operator-(Vector a,Vector b){return (Vector){a.x-b.x,a.y-b.y};}
Vector operator*(Vector a,double k){return (Vector){a.x*k,a.y*k};}
Vector operator/(Vector a,double k){return (Vector){a.x/k,a.y/k};}
double Dot(Vector a,Vector b)
{
    return a.x*b.x+a.y*b.y;
}
double Cross(Vector a,Vector b)
{
    return a.x*b.y-a.y*b.x;
}
bool cmp(Point a,Point b)
{
    if(a.x!=b.x)return a.x<b.x;
    else return a.y<b.y;
}
struct Monotonous_Queue
{
    int L,R;
    Point Q[N];
    void clear()
    {
        L=1;R=0;
        memset(Q,0,sizeof(Q));
    }
    void push(Point o,int flag)
    {
        while(L<=R && (L!=R&&dcmp(Cross(o-Q[R-1],Q[R]-Q[R-1])*flag)<=0))R--;
        Q[++R]=o;
    }
    double query()
    {
        double ans=0;       
        for(int i=L;i<R;i++)ans+=0.5*fabs(Cross(Q[i],Q[i+1]));
        return ans;
    }
}q;
int a[N],b[N];
int main()
{
    int n,i;
    double ans=0;
    n=read();
    for(i=1;i<=n;i++)a[i]=read(),b[i]=b[i-1]+a[i];
    for(i=1;i<=n;i++)p[i]=(Point){(double)b[i],(double)b[i]/(double)a[i]};
    
    sort(p+1,p+n+1,cmp);
    q.clear();
    for(i=1;i<=n;i++)q.push(p[i],+1);
    ans+=q.query();
    q.clear();
    for(i=1;i<=n;i++)q.push(p[i],-1);
    ans+=q.query();
    printf("%.5lf",ans);
    return 0;
}