李超线段树板子
P4254 [JSOI2008]Blue Mary开公司 板子题
内有注释
Code
#include<bits/stdc++.h> #define ls (x << 1) #define rs (x << 1 | 1) using namespace std; const int N = 500005; int n, len, T[N << 2]; //T里面存某条线段的编号 double k[N << 1] , b[N << 1]; //记录斜率和b值 double f (int pos, int x) { return k[pos] * (x - 1) + b[pos]; } //计算函数值 void update (int x , int l , int r , int c){ if (l == r){ if(f(c , l) > f(T[x] , l)) T[x] = c; //如果当前线段在l处的值比原来的大的话就更新 return ; } int mid = (l + r) >> 1; //如果斜率较小 if (k[T[x]] < k[c]) { //比较x的中点函数值,如果比mid大 //就先递归下去,再更新,防止线段丢失 if (f(c, mid) > f(T[x] , mid)) update(ls, l, mid, T[x]), T[x] = c; else update(rs, mid + 1, r, c);//否则直接递归 } if (k[T[x]] > k[c]) {//同理 if (f(c, mid) > f(T[x], mid)) update(rs, mid + 1, r, T[x]), T[x] = c; else update(ls, l, mid, c) ; } } double query (int x, int l, int r, int c){ if (l == r) return f(T[x] , c); int mid = (l + r) >> 1; if (c <= mid) return max(f(T[x], c), query(ls, l, mid, c)); else return max(f(T[x], c), query(rs, mid + 1, r, c)); } int main() { //freopen("1568_12.in","r",stdin); //freopen("cjhyyds.txt","w",stdout); cin >> n; char ch[23]; while(n --) { scanf("%s", ch); if(ch[0] == 'P') { len++ ; scanf ("%lf %lf", &b[len], &k[len]) ; update(1, 1, N, len); } else { int x; scanf ("%d", &x); double slm = query(1, 1, N, x); printf ("%d ",(int)(slm / 100)) ; } } return 0; }