李超线段树模板题,要同时维护最大值和最小值,然后求交点的时候注意 double 的转换
code:
#include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <vector> #include <algorithm> #include <string> #define N 600007 #define eps 1e-14 #define ll long long #define lson now<<1 #define rson now<<1|1 using namespace std; void setIO(string s) { string in=s+".in"; string out=s+".out"; freopen(in.c_str(),"r",stdin); // freopen(out.c_str(),"w",stdout); } int cor[N],n,Q; // y=kx+b struct Line { int l,r; ll k,b; Line(int l=0,int r=0,ll k=0,ll b=0):l(l),r(r),k(k),b(b){} ll calc(ll pos) { return pos*k+b; } double cross(Line t) { return (double)(b-t.b)/(t.k-k); } }smax[N<<2],smin[N<<2]; void build(int l,int r,int now) { smax[now]=Line(l,r,0,0); smin[now]=Line(l,r,0,0); if(l==r) return; int mid=(l+r)>>1; build(l,mid,lson),build(mid+1,r,rson); } void upmax(int l,int r,int now,Line k) { if(l>=k.l&&r<=k.r) { if(k.calc(cor[l])>smax[now].calc(cor[l])&&k.calc(cor[r])>smax[now].calc(cor[r])) smax[now]=k; else if(k.calc(cor[l])>smax[now].calc(cor[l])||k.calc(cor[r])>smax[now].calc(cor[r])) { int mid=(l+r)>>1; if(k.calc(cor[mid])>smax[now].calc(cor[mid])) { Line tmp=smax[now]; smax[now]=k,k=tmp; } // 交点在中点右面 if(smax[now].cross(k)-(double)cor[mid]>eps) upmax(mid+1,r,rson,k); else upmax(l,mid,lson,k); } return; } int mid=(l+r)>>1; if(k.l<=mid) upmax(l,mid,lson,k); if(k.r>mid) upmax(mid+1,r,rson,k); } void upmin(int l,int r,int now,Line k) { if(l>=k.l&&r<=k.r) { if(k.calc(cor[l])<smin[now].calc(cor[l])&&k.calc(cor[r])<smin[now].calc(cor[r])) smin[now]=k; else if(k.calc(cor[l])<smin[now].calc(cor[l])||k.calc(cor[r])<smin[now].calc(cor[r])) { int mid=(l+r)>>1; if(k.calc(cor[mid])<smin[now].calc(cor[mid])) { Line tmp=smin[now]; smin[now]=k,k=tmp; } if(smin[now].cross(k)-(double)cor[mid]>eps) upmin(mid+1,r,rson,k); else upmin(l,mid,lson,k); } return; } int mid=(l+r)>>1; if(k.l<=mid) upmin(l,mid,lson,k); if(k.r>mid) upmin(mid+1,r,rson,k); } ll qmax(int l,int r,int now,int p) { if(l==r) return smax[now].calc(cor[l]); int mid=(l+r)>>1; ll re=smax[now].calc(cor[p]); if(p<=mid) return max(re,qmax(l,mid,lson,p)); else return max(re,qmax(mid+1,r,rson,p)); } ll qmin(int l,int r,int now,int p) { if(l==r) return smin[now].calc(cor[p]); int mid=(l+r)>>1; ll re=smin[now].calc(cor[p]); if(p<=mid) return min(re,qmin(l,mid,lson,p)); else return min(re,qmin(mid+1,r,rson,p)); } struct li { int s,t; ll k,b; li(int s=0,int t=0,ll k=0,ll b=0):s(s),t(t),k(k),b(b){} }; vector<li>G[N]; int a[N],A[N],ask[N]; int main() { // setIO("input"); scanf("%d%d",&n,&Q); for(int i=1;i<=n;++i) { scanf("%d",&a[i]); G[i].push_back(li(0,1e9,0,a[i])); } char op[10]; int q=0,tot=0; A[++tot]=0,A[++tot]=1e9; for(int i=1;i<=Q;++i) { int t; scanf("%d%s",&t,op),A[++tot]=t; if(op[0]=='c') { int x,k; scanf("%d%d",&x,&k); G[x][G[x].size()-1].t=t; li pr=G[x][G[x].size()-1]; G[x].push_back(li(t,1e9,k,pr.k*t+pr.b-(ll)k*t)); } else ask[++q]=t; } sort(A+1,A+1+tot); int T=unique(A+1,A+1+tot)-A-1; for(int i=1;i<=T;++i) cor[i]=A[i]; for(int i=1;i<=q;++i) ask[i]=lower_bound(A+1,A+1+T,ask[i])-A; for(int i=1;i<=n;++i) { for(int j=0;j<G[i].size();++j) { G[i][j].s=lower_bound(A+1,A+1+T,G[i][j].s)-A; G[i][j].t=lower_bound(A+1,A+1+T,G[i][j].t)-A; } } build(1,T,1); for(int i=1;i<=n;++i) { for(int j=0;j<G[i].size();++j) { Line k=Line(G[i][j].s,G[i][j].t,G[i][j].k,G[i][j].b); upmax(1,T,1,k); upmin(1,T,1,k); } } for(int i=1;i<=q;++i) printf("%lld\n",max(qmax(1,T,1,ask[i]),-qmin(1,T,1,ask[i]))); return 0; }