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; }