【JSOI2008】Blue Mary开公司 李超线段树

来源:互联网 发布:淘宝详情页打不开 编辑:程序博客网 时间:2024/04/28 17:52
F.A.Qs Home Discuss ProblemSet Status Ranklist Contest 入门OJ LoginRegister 捐赠本站


Notice:为保证OJ试题质量,今后添加的试题如有发现出现重复,请联系我们删除,谢谢!



Problem 1568. – [JSOI2008]Blue Mary开公司

1568: [JSOI2008]Blue Mary开公司

Time Limit: 15 Sec  Memory Limit: 162 MB
Submit: 1200  Solved: 418
[Submit][Status][Discuss]

Description

Input

第一行 :一个整数N ,表示方案和询问的总数。 
接下来N行,每行开头一个单词“Query”或“Project”。 
若单词为Query,则后接一个整数T,表示Blue Mary询问第T天的最大收益。 
若单词为Project,则后接两个实数S,P,表示该种设计方案第一天的收益S,以及以后每天比上一天多出的收益P。
1 <= N <= 100000 1 <= T <=50000 0 < P < 100,| S | <= 10^6 
提示:本题读写数据量可能相当巨大,请选手注意选择高效的文件读写方式。

Output

对于每一个Query,输出一个整数,表示询问的答案,并精确到整百元(以百元为单位,

例如:该天最大收益为210或290时,均应该输出2)。没有方案时回答询问要输出0

Sample Input

10
Project 5.10200 0.65000
Project 2.76200 1.43000
Query 4
Query 2
Project 3.80200 1.17000
Query 2
Query 3
Query 1
Project 4.58200 0.91000
Project 5.36200 0.39000

Sample Output

0
0
0
0
0

HINT

Source

[Submit][Status][Discuss]

HOMEBack


题解:李超线段树,超哥线段树一般可以处理一些区间线段的题目,可以维护线段或直线。
上个图,原图出自网络,侵删。
这里写图片描述

其实就是维护某个区间的答案,每个区间的答案就是该区间最长的那条线段的答案,有交点的部分怎么办?因为查询的时候是递归到叶子结点更新答案,所以所有应该遍历到的线段都会被遍历到。
更新答案的时候注意判断的方式,通过存储斜率k和截距b来实现。
这道题注意作弊范围和精度。

代码:

#include<iostream>#include<cstdio>#include<cmath>#define MAXN 100005using namespace std;struct node{    double k,b;}tree[MAXN*8];int n;double min(double x,double y){    if (x<y) return x;    return y;}void update(int root,int l,int r,double k,double b) {    if (!tree[root].b&&!tree[root].k)     {        tree[root].b=b;tree[root].k=k;        return ;    }    int mid=(l+r)>>1;    double x=(mid-1.0)*tree[root].k+tree[root].b;    double y=(mid-1.0)*k+b;    if (l==r)    {        if (y>x) tree[root].k=k,tree[root].b=b;        return;    }    if (tree[root].k>=k&&tree[root].b>b)        return ;    if (k>=tree[root].k&&b>tree[root].b)    {        tree[root].k=k;tree[root].b=b;        return ;    }    if (tree[root].k*(l-1)+tree[root].b>k*(l-1)+b&&tree[root].k>k) return ;    else if (tree[root].k>k)    {        if (x>=y)            update(root*2,l,mid,k,b);        else        {            update(root*2+1,mid+1,r,tree[root].k,tree[root].b);            tree[root].k=k;tree[root].b=b;        }    }    else    {        if (x>=y)            update(root*2+1,mid+1,r,k,b);        else        {            update(root*2,l,mid,tree[root].k,tree[root].b);            tree[root].k=k;            tree[root].b=b;        }    }}double query(int root,int l,int r,int x){    int mid=(l+r)>>1;double tmp=0;    tmp=max(tmp,(x-1.0)*tree[root].k+tree[root].b);    if (l==r) return tmp;    if (x<=mid) tmp=max(tmp,query(root*2,l,mid,x));    else if (x>mid) tmp=max(tmp,query(root*2+1,mid+1,r,x));    return tmp;}int main(){    char c[100];    int x;double k,b;    scanf("%d",&n);    for (int i=1;i<=n;i++)    {        scanf("%s",c);        if (c[0]=='Q')        {            scanf("%d",&x);            double ans=0;            ans=query(1,1,50000,x);            ans=floor(ans/100);            printf("%.0lf\n",ans);        }        else if (c[0]=='P')        {            scanf("%lf%lf",&b,&k);            update(1,1,50000,k,b);        }    }}
阅读全文
0 0
原创粉丝点击