[Luogu] P4254 [JSOI2008]Blue Mary开公司

题目背景

Blue Mary 最近在筹备开一家自己的网络公司。由于他缺乏经济头脑,所以先后聘请了若干个金融顾问为他设计经营方案。

题目描述

万事开头难,经营公司更是如此。开始的收益往往是很低的,不过随着时间的增长会慢慢变好。也就是说,对于一个金融顾问 iii,他设计的经营方案中,每天的收益都比前一天高,并且均增长一个相同的量 PiP_iPi

由于金融顾问的工作效率不高,所以在特定的时间,Blue Mary 只能根据他已经得到的经营方案来估算某一时间的最大收益。由于 Blue Mary 是很没有经济头脑的,所以他在估算每天的最佳获益时完全不会考虑之前的情况,而是直接从所有金融顾问的方案中选择一个在当天获益最大的方案的当天的获益值,例如:

有如下两个金融顾问分别对前四天的收益方案做了设计:

 第一天第二天第三天第四天Pi
顾问 1 1 5 9 13 4
顾问 2 2 5 8 11 3

在第一天,Blue Mary认为最大收益是 2(使用顾问 2 的方案),而在第三天和第四天,他认为最大收益分别是 9 和 13(使用顾问 1 的方案)。而他认为前四天的最大收益是:

2+5+9+13=29

现在你作为 Blue Mary 公司的副总经理,会不时收到金融顾问的设计方案,也需要随时回答 Blue Mary 对某天的“最大收益”的询问(这里的“最大收益”是按照 Blue Mary 的计算方法)。一开始没有收到任何方案时,你可以认为每天的最大收益值是 0。下面是一组收到方案和回答询问的例子:

  • 询问 2
  • 回答 0
  • 收到方案:0 1 2 3 4 5 ……
  • 询问 2
  • 回答 1
  • 收到方案:2 2.1 2.2 2.3 2.4 ……
  • 询问 2
  • 回答 2.1

输入输出格式

输入格式:

 

第一行 :一个整数 N ,表示方案和询问的总数。

接下来 N 行,每行开头一个单词QueryProject

若单词为Query,则后接一个整数 T,表示 Blue Mary 询问第 T 天的最大收益。

若单词为Project,则后接两个实数 S,P,表示该种设计方案第一天的收益 S,以及以后每天比上一天多出的收益 P。

 

输出格式:

 

对于每一个Query,输出一个整数,表示询问的答案,并精确到整百元(以百元为单位,例如:该天最大收益为 210 或 290 时,均应该输出 2)。没有方案时回答询问要输出 0。

题目解析

鲤抄李超树模板题

李超树是某种用来维护关于斜率的玄学线段树,偷一张网上常见的图:

其实李超树就是用线段树维护凸壳,细节还是值得注意的

Code

#include<iostream>
#include<cstdio>
using namespace std;

const int MAXN = 500000 + 5;

int n,m;
int tree[MAXN<<2];
double k[MAXN<<1],b[MAXN<<1];

inline double f(int w,int x) {
    return k[w] * (x-1) + b[w];
}

void add(int L,int R,int pos,int x) {
    if(L == R) {
        if(f(x,L) > f(tree[pos],L)) tree[pos] = x;
        return;
    }
    int mid = (L + R) >> 1;
    if(k[tree[pos]] < k[x]) {
        if(f(x,mid) > f(tree[pos],mid)) {
            add(L,mid,pos<<1,tree[pos]);
            tree[pos] = x;
        } else add(L,mid,pos<<1|1,x);
    }
    if(k[tree[pos]] > k[x]) {
        if(f(x,mid) > f(tree[pos],mid)) {
            add(mid+1,R,pos<<1|1,tree[pos]);
            tree[pos] = x;
        } else add(L,mid,pos<<1,x);
    }
}

double query(int L,int R,int pos,int x) {
    if(L == R) return f(tree[pos],x);
    int mid = (L + R) >> 1;
    if(x <= mid) return max(f(tree[pos],x),query(L,mid,pos<<1,x));
    else return max(f(tree[pos],x),query(mid+1,R,pos<<1|1,x));
}

int main() {
    scanf("%d",&n);
    int x;char opt[10];
    while(n--) {
        scanf("%s",opt);
        if(opt[0] == 'P') {
            m++;
            scanf("%lf%lf",&b[m],&k[m]);
            add(1,MAXN,1,m);
        } else {
            scanf("%d",&x);
            printf("%d\n",int(query(1,MAXN,1,x) / 100));
        }
    }
    return 0;
}

 

posted @ 2018-09-21 15:41  Floatiy  阅读(232)  评论(1编辑  收藏  举报