李超线段树板子

李超线段树板子

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\n",(int)(slm / 100)) ;
        }
    }
    return 0;
}

 

posted @ 2021-05-19 17:04  liujunxi  阅读(63)  评论(0编辑  收藏  举报