• 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
    ",(ll)((temp.k * pos + temp.b) / 100 + 1e-8));
                }
            }
        }
    
        return 0;
    }
  • 相关阅读:
    D. Time to Run【构造】
    P3388 割顶 【求割点个数】
    处女座的测验 素数,构造
    处女座与复读机 DP
    求一个分数小数点后指定位数的数字
    安卓开发创建活动,布局,添加按钮,she使用Toast,设菜单,使菜单相关联等操作
    三进制 处女座的砝码 高精度
    上海高校程序设计联赛 D-CSL的字符串 栈模拟
    区间DP经典 石子合并
    区间DP 洛谷P2858牛奶零食
  • 原文地址:https://www.cnblogs.com/zbtrs/p/8432902.html
Copyright © 2020-2023  润新知