bzoj 1568: [JSOI2008]Blue Mary开公司

1568: [JSOI2008]Blue Mary开公司

Time Limit: 15 Sec  Memory Limit: 162 MB
Submit: 1100  Solved: 386
[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
超哥线段树

线段树的每个结点上存的是这个区间对应的一条线段。

插入时,新线段完全更劣,则不进行修改

新线段完全更优,替换旧线段,向下update,若部分更优,把优的部分多的那条线段留在这个结点,

把另一条线段较优的那部分截出来,更新该节点子树

#include<algorithm>
#include<iostream>
#include<cstdio>
using namespace std;
#define N 500004
double a[N*2],b[N*2];
int tree[N*4],n,cnt=0;

inline bool check(int i,int j,int k) 
{
    return a[i]+b[i]*(k-1)>a[j]+b[j]*(k-1);
}
inline double calc(int k,int x)
{
    return (a[k]+b[k]*(x-1));
}
void modify(int l,int r,int rt,int x)
{
    if(l==r)
    {
        if(check(x,tree[rt],l)) tree[rt]=x;
        return;
    }
    int mid=(l+r)>>1;
    if(b[x]>b[tree[rt]])
    {
        if(check(x,tree[rt],mid)) modify(l,mid,rt<<1,tree[rt]),tree[rt]=x;
        else modify(mid+1,r,rt<<1|1,x);
    } 
    if(b[x]<=b[tree[rt]])
    {
        if(check(x,tree[rt],mid))modify(mid+1,r,rt<<1|1,tree[rt]),tree[rt]=x;
            else modify(l,mid,rt<<1,x);
    }
 } 
double query(int l,int r,int rt,int x)
{
    if(l==r) return calc(tree[rt],x);
    int mid=(l+r)>>1;
    double ans = calc(tree[rt],x);
    if(x<=mid) ans=max(ans,query(l,mid,rt<<1,x));
    if(x>mid)ans=max(ans,query(mid+1,r,rt<<1|1,x));
    return ans;
}
int main()
{
    scanf("%d",&n);
    char s[20];
    while(n--)
    {
        scanf("%s",s);
        if(s[0]=='P')
        {
            
            scanf("%lf%lf",&a[cnt],&b[cnt]);
            modify(1,N,1,cnt);
        }
        else {
            int x;
            
            scanf("%d",&x);
            double tmp=query(1,N,1,x);
            int ans=tmp/100.00;
            printf("%d
",ans);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/sssy/p/7309772.html