bzoj1568 [JSOI2008]Blue Mary开公司

1568: [JSOI2008]Blue Mary开公司

Time Limit: 15 Sec  Memory Limit: 162 MB
Submit: 1709  Solved: 595
[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
分析:传说中的标记永久化......
          我个人感觉标记永久化就是记录当前区间可能的最优解,便于和从子区间传回的最优解进行比较,看到底谁才是最优解.这道题实际上就是给定若干条直线,求给定横坐标的y值最大的点.利用线段树维护,每个区间记录当前可能的最优解.在区间中点mid处x高于t,说明在区间[L,R]中最优解可能是x,于是在[L,R]上打标机记录直线x.因为两条直线的交点在mid左边,所以左边区间应该打上t的标记(t更有可能成为最优解).就这样不断地修改下去.
       查询就是单点查询.返回一条直线,每次将返回的直线与当前区间标记的直线在查询的位置x处比较y值大小,将更优的传上去就好了.
       自己理解的标记永久化就是这样了,不能确定最优解时就记录在当前层最有可能的最优解,最后比较返回.
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

typedef long long ll;
const int maxn = 50010;
int q,n = 50000;
bool flag = false,vis[maxn << 2];

struct node
{
    double k,b;
    int id;
} e[maxn << 2];

bool cmp(node a,node b,int pos)
{
    double temp1 = (double)a.k * pos + a.b;
    double temp2 = (double)b.k * pos + b.b;
    return temp1 < temp2;
}

double jiao(node a,node b)
{
    return (double)(a.b - b.b) / (b.k - a.k);
}

void update(int o,int l,int r,int x,int y,node a)
{
    int mid = (l + r) >> 1;
    if (x <= l && r <= y)
    {
        if (!vis[o])
        {
            vis[o] = 1;
            e[o] = a;
        }
        else
        {
            double l1 = a.b + (double)a.k * l,l2 = a.b + (double)a.k * r;
            double r1 = e[o].b + (double)e[o].k * l,r2 = e[o].b + (double)e[o].k * r;
            if (l1 <= r1 && l2 <= r2)
                return;
            if (l1 >= r1 && l2 >= r2)
                e[o] = a;
            else
            {
                double X = jiao(e[o],a);
                if (l1 >= r1)
                {
                    if (X <= mid)
                        update(o * 2,l,mid,x,y,a);
                    else
                        update(o * 2 + 1,mid + 1,r,x,y,e[o]),e[o] = a;
                }
                else
                {
                    if (X > mid)
                        update(o * 2 + 1,mid + 1,r,x,y,a);
                    else
                        update(o * 2,l,mid,x,y,e[o]),e[o] = a;
                }
            }
        }
        return;
    }
    if (x <= mid)
        update(o * 2,l,mid,x,y,a);
    if (y > mid)
        update(o * 2 + 1,mid + 1,r,x,y,a);
}

node query(int o,int l,int r,int pos)
{
    if (l == r)
        return e[o];
    int mid = (l + r) >> 1;
    node temp;
    if (pos <= mid)
        temp = query(o * 2,l,mid,pos);
    else
        temp = query(o * 2 + 1,mid + 1,r,pos);
    if (cmp(temp,e[o],pos) == 1)
        return e[o];
    else
        return temp;
}

int main()
{
    scanf("%d",&q);
    while (q--)
    {
        char ch[10];
        double x,y;
        scanf("%s",ch);
        if (ch[0] == 'P')
        {
            flag = true;
            scanf("%lf%lf",&x,&y);
            node temp;
            temp.k = y;
            temp.b = x - y;
            temp.id = 1;
            update(1,1,n,1,n,temp);
        }
        else
        {
            int pos;
            scanf("%d",&pos);
            if (!flag)
                puts("0");
            else
            {
                node temp = query(1,1,n,pos);
                printf("%lld\n",(ll)((temp.k * pos + temp.b) / 100 + 1e-8));
            }
        }
    }

    return 0;
}

 

 

posted @ 2018-02-08 19:18  zbtrs  阅读(198)  评论(0编辑  收藏  举报