UOJ #88. 【集训队互测2015】Robot 李超线段树
李超线段树模板题,要同时维护最大值和最小值,然后求交点的时候注意 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;
}

浙公网安备 33010602011771号