正睿 2019 省選十連測 Day1 T1 終
阿新 • • 發佈:2018-12-03
把題目給出的式子化簡一下
得到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; }