BZOJ 1568: [JSOI2008]Blue Mary开公司 (李超线段树)
第一次学这个东西,感觉还是挺好写 + 好用的.
code:
#include <bits/stdc++.h>
#define ll long long
#define M 50000
#define N 100008
#define eps 1e-12
#define lson now<<1
#define rson now<<1|1
#define comp(a,b) ((a-b)>eps)
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);
}
// y=kx+b
struct Line
{
double k,b;
int l,r,flag;
Line(int a1=0,int b1=0,double c1=0,double d1=0):l(a1),r(b1),k(c1),b(d1){}
double calc(int pos) { return k*pos+b; }
double cross(Line t) { return (b-t.b)/(t.k-k); }
}s[N<<2];
int n;
void build(int l,int r,int now)
{
s[now].k=s[now].b=0;
s[now].l=1,s[now].r=M,s[now].flag=-1;
if(l==r) return;
int mid=(l+r)>>1;
build(l,mid,lson),build(mid+1,r,rson);
}
void update(int l,int r,int now,Line k)
{
if(l>=k.l&&r<=k.r)
{
if(k.calc(l)-s[now].calc(l)>eps&&k.calc(r)-s[now].calc(r)>eps)
s[now]=k;
else if(k.calc(l)-s[now].calc(l)>eps||k.calc(r)-s[now].calc(r)>eps)
{
int mid=(l+r)>>1;
if(k.calc(mid)-s[now].calc(mid)>eps)
{
Line tmp=k;
k=s[now],s[now]=tmp;
}
if(k.cross(s[now])-mid<-eps)
update(l,mid,lson,k);
else update(mid+1,r,rson,k);
}
return;
}
int mid=(l+r)>>1;
if(k.l<=mid) update(l,mid,lson,k);
if(k.r>mid) update(mid+1,r,rson,k);
}
double query(int l,int r,int now,int p)
{
if(l==r) return s[now].calc(p);
int mid=(l+r)>>1;
double ans=s[now].calc(p);
if(p<=mid) ans=max(ans,query(l,mid,lson,p));
else ans=max(ans,query(mid+1,r,rson,p));
return ans;
}
int main()
{
// setIO("input");
scanf("%d",&n);
build(1,M,1);
for(int i=1;i<=n;++i)
{
char op[10];
scanf("%s",op);
if(op[0]=='P')
{
double s,p;
scanf("%lf%lf",&s,&p);
Line now=Line(1,M,p,s-p);
update(1,M,1,now);
}
else
{
int x;
scanf("%d",&x);
int ans=(int)floor(query(1,M,1,x)/100);
printf("%d\n",ans);
}
}
return 0;
}

浙公网安备 33010602011771号