题意
给出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,那么就得到了一些直线。最优的答案一定在某条最上方或最下方的直线上,半平面交或凸包即可。
代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }