雜題集萃[1]
阿新 • • 發佈:2018-09-14
register c++ n+1 pac sdi \n line 數據 name
題意
給出 $N$ 個形如 $f_i(x)=a_ix^2+b_i$ 的二次函數。
有 $Q$ 次詢問,每次給出一個 $x$,詢問 $max(f_i(x))$。
輸入格式
第一行兩個整數 $N$,$Q$。
接下來的 $N$ 行,每行兩個整數 $a_i$,$b_i$。
接下來的 $Q$ 行,每行一個整數 $x$。
輸出格式
對於每個詢問,輸出一行一個整數表示答案。
input
2 4
3 0
4 -2
-1
0
1
2
output
6
0
3
12
限制與約定
每個測試點 $10$ 分,共 $10$ 個測試點:
對於所有的數據,有:
$1≤N,Q,|x_i|,|a_i|,|b_i|<32323$。
時間限制:1s
================================
題解
這道題看似是數據結構,但可以離線處理。
我們只要排一遍序維護一個凸殼就行了。
當$x<0$時將 $b_i$乘上$-1$就行了。QAQ
==================================
code
#include <bits/stdc++.h> #define int long long #define re register int using namespace std; inline void read(int &x){ x=0;char ch=getchar();bool f=0; for(;!isdigit(ch);ch=getchar())f|=(ch=='-'); for(;isdigit(ch);ch=getchar())x=(x<<1)+(x<<3)+(ch^48); x=f?-x:x; } const int N=5e5+10,M=32323; int t,k[N],b[N],id[N],n,q,p[N],a1[M+1],a2[M+1]; inline int f(int x,int i){return k[x]*i*i+b[x]*i;} inline int cmp(int x,int y){return (k[x]==k[y])?b[x]<b[y]:k[x]<k[y];} inline double check(int i,int j){return 1.0*(b[j]-b[i])/(k[i]-k[j]);} signed main(){ read(n),read(q); for(re i=1;i<=n;++i) read(k[i]),read(b[i]),id[i]=i; sort(id+1,id+n+1,cmp);t=0; for(re i=1;i<=n;++i){ while(t&&k[id[i]]==k[p[t]]) --t; while(t>1&&check(id[i],p[t])<=check(p[t],p[t-1])) --t; p[++t]=id[i]; } for(re i=1,j=1;i<=M;++i){ while(j<t&&f(p[j],i)<=f(p[j+1],i)) ++j; a1[i]=f(p[j],i); } for(re i=1;i<=n;++i) b[i]=-b[i],p[i]=0; sort(id+1,id+n+1,cmp);t=0; for(re i=1;i<=n;++i){ while(t&&k[id[i]]==k[p[t]]) --t; while(t>1&&check(id[i],p[t])<=check(p[t],p[t-1])) --t; p[++t]=id[i]; } for(re i=1,j=1;i<=M;++i){ while(j<t&&f(p[j],i)<=f(p[j+1],i)) ++j; a2[i]=f(p[j],i); } while(q--){ int x;read(x); if(x>0)printf("%lld\n",a1[x]); if(x==0) puts("0"); if(x<0)printf("%lld\n",a2[-x]); } return 0; }
雜題集萃[1]