洛谷 4254 Blue Mary 開公司
阿新 • • 發佈:2021-10-08
新增線性函式 $f(x)$,詢問 $x$ 取某個整數時最大的函式值;
李超樹模板
[JSOI2008] Blue Mary開公司
題面
題解
李超樹模板題
線段樹每個節點記錄一條直線。考慮新增一條直線,若該直線在區間內全面大於記錄的直線,則更新;全面小於,則棄去;否則遞迴兩個子節點。
如此一來,每個新增的線段都在其優勢位置得到了記錄。
單點詢問,取log層的最大值即可。
程式碼
//https://www.luogu.com.cn/problem/P4254 // nksbwen 20210727 #include <cstdio> #include <algorithm> using std::max; const int MAXT=50011; int N; struct Func{ double s, d; } Zero, op; double Cal(Func f, int t){ return f.s+(t-1)*f.d; } bool Up(Func a, Func b, int c){ return Cal(a, c)>Cal(b, c); } struct Node{ int l, r; Func f; } T[MAXT<<2]; void Build(int l, int r, int at=1){ T[at].l=l;T[at].r=r; T[at].f=Zero; if(l==r) return; int m=(l+r)>>1; Build(l, m, at<<1); Build(m+1, r, (at<<1)|1); } void Update(int at){ bool l=Up(op, T[at].f, T[at].l), r=Up(op, T[at].f, T[at].r); if(l==r){ if(l && r) T[at].f=op; return; } Update(at<<1);Update((at<<1)|1); } int opt; double Ask(int at){ if(T[at].l==T[at].r) return Cal(T[at].f, opt); int m=(T[at].l+T[at].r)>>1; double ret=Cal(T[at].f, opt); if(opt<=m) return max(ret, Ask(at<<1)); else return max(ret, Ask((at<<1)|1)); } int main(){ scanf("%d", &N); int MaxT=50000; Build(1, MaxT); char cmd[111]; for(int i=1;i<=N;++i){ scanf("%s", cmd); if(cmd[0]=='P'){ scanf("%lf%lf", &op.s, &op.d); Update(1); } else{ scanf("%d", &opt); printf("%d\n", (int)(Ask(1)/100.0)); } } return 0; }