题意

给出N 个形如$f_i(x) = a_i x^2 + b_i x $的二次函数。

有Q 次询问,每次给出一个x,询问$max{\{f_i(x)\}}$。$N,Q \leq 5*10^5$。


 

思考

首先将x大于0还是小于0分类,对于某一类全都除以x,那么就得到了一些直线。最优的答案一定在某条最上方或最下方的直线上,半平面交或凸包即可。


 

代码

  1 // luogu-judger-enable-o2
  2 #pragma GCC optimize 2
  3 #include<bits/stdc++.h>
  4 using namespace std;
  5 typedef long long int ll;
  6 typedef long double ld;
  7 const int maxn=5E5+5;
  8 const int base=33333;
  9 const ld eps=1E-10;
 10 const ld inf=1E17;
 11 int n,m,T;
 12 ll a[maxn],b[maxn],ans[maxn];
 13 int idR[maxn],idL[maxn];
 14 ld rightPlane[maxn],leftPlane[maxn];
 15 int q[maxn];
 16 struct pt
 17 {
 18     double x,y;
 19     pt(double a=0,double b=0):x(a),y(b){}
 20     pt operator+(const pt&A){return pt(x+A.x,y+A.y);}
 21     pt operator-(const pt&A){return pt(x-A.x,y-A.y);}
 22     pt operator*(ld d){return pt(x*d,y*d);}
 23     double operator*(const pt&A){return x*A.y-y*A.x;}
 24     void out(){cout<<"("<<x<<","<<y<<")"<<endl;}
 25 };
 26 struct line
 27 {
 28     pt A,B;
 29     int id,b;
 30     int slope;
 31     line(){}
 32     line(pt a,pt b):A(a),B(b){}
 33 }s[maxn];
 34 inline ll max(ll x,ll y)
 35 {
 36     return x>y?x:y;
 37 }
 38 inline ll min(ll x,ll y)
 39 {
 40     return x<y?x:y;
 41 }
 42 inline ll get(ll x,ll a,ll b)
 43 {
 44     return (a*x+b)*x;
 45 }
 46 inline int read()
 47 {
 48     bool flag=0;
 49     char ch=getchar();
 50     if(ch=='-')
 51         flag^=1;
 52     while(!isdigit(ch))
 53     {
 54         ch=getchar();
 55         if(ch=='-')
 56             flag^=1;
 57     }
 58     int sum=ch-'0';
 59     ch=getchar();
 60     while(isdigit(ch))
 61     {
 62         sum=sum*10+ch-'0';
 63         ch=getchar();
 64     }
 65     return flag?-sum:sum;
 66 }
 67 void write(ll x)
 68 {
 69     if(x>=10)
 70         write(x/10);
 71     putchar('0'+x%10);
 72 }
 73 inline void writen(ll x)
 74 {
 75     if(x<0)
 76     {
 77         putchar('-');
 78         write(-x);
 79     }
 80     else
 81         write(x);
 82     putchar('\n');
 83 }
 84 inline int cross(pt A,pt B)
 85 {
 86     ld d=A*B;
 87     if(abs(d)<=eps)
 88         return 0;
 89     return d>0?1:-1;
 90 }
 91 inline pt intersection(line a,line b)
 92 {
 93     pt A=b.B-b.A,B=a.B-a.A,C=b.A-a.A;
 94     if(cross(A,B)==0)
 95         return pt(inf,inf);
 96     ld d=-(B*C)/(B*A);
 97     return b.A+A*d;
 98 }
 99 inline int onClockwise(line a,line b,line c)
100 {
101     return cross(a.B-a.A,intersection(b,c)-a.A)==-1;
102 }
103 bool cmpR(line A,line B)
104 {
105     if(A.slope==B.slope)
106         return A.b<B.b;
107     return A.slope<B.slope;
108 }
109 bool cmpL(line A,line B)
110 {
111     if(A.slope==B.slope)
112         return A.b>B.b;
113     return A.slope<B.slope;
114 }
115 void initR()
116 {
117     sort(s+1,s+n+1,cmpR);
118     int L=1,R=0;
119     for(int i=1;i<=n;++i)
120     {
121         while(i!=n&&s[i].slope==s[i+1].slope)
122             ++i;
123         while(R-1>=L&&onClockwise(s[i],s[q[R]],s[q[R-1]]))
124             --R;
125         q[++R]=i;
126     }
127     for(int i=1;i<=R;++i)
128         idR[i]=s[q[i]].id;
129     for(int i=1;i<R;++i)
130         rightPlane[i]=intersection(s[q[i]],s[q[i+1]]).x;
131     int pos=1;
132     for(int i=-base;i<=base;++i)
133     {
134         while(pos<R&&rightPlane[pos]<ld(i))
135             ++pos;
136         ans[i+base]=get(i,s[q[pos]].slope,s[q[pos]].b);
137     }
138 }
139 void initL()
140 {
141     sort(s+1,s+n+1,cmpL);
142     int L=1,R=0;
143     for(int i=1;i<=n;++i)
144     {
145         while(i!=n&&s[i].slope==s[i+1].slope)
146             ++i;
147         while(R-1>=L&&onClockwise(s[i],s[q[R]],s[q[R-1]]))
148             --R;
149         q[++R]=i;
150     }
151     for(int i=1;i<=R;++i)
152         idL[i]=s[q[i]].id;
153     for(int i=1;i<R;++i)
154         leftPlane[i]=intersection(s[q[i]],s[q[i+1]]).x;
155     int pos=1;
156     for(int i=base;i>=-base;--i)
157     {
158         while(pos<R&&ld(i)<leftPlane[pos])
159             ++pos;
160         ans[i+base]=max(ans[i+base],get(i,s[q[pos]].slope,s[q[pos]].b));
161     }
162 }
163 int main()
164 {
165 //    freopen("A.in","r",stdin);
166 //    freopen("A.out","w",stdout);
167     ios::sync_with_stdio(false);
168     n=read(),T=read();
169     for(int i=1;i<=n;++i)
170     {
171         a[i]=read(),b[i]=read();
172         s[i].A=pt(0,b[i]);
173         s[i].B=pt(1,a[i]+b[i]);
174         s[i].slope=a[i];
175         s[i].b=b[i];
176         s[i].id=i;
177     }
178     initR();
179     for(int i=1;i<=n;++i)
180         swap(s[i].A,s[i].B);
181     initL();
182     while(T--)
183     {
184         int x=read();
185         writen(ans[x+base]);
186     }
187     return 0;
188 }
View Code

 

 posted on 2019-09-20 06:42  GreenDuck  阅读(205)  评论(0编辑  收藏  举报