• BZOJ1568: [JSOI2008]Blue Mary开公司【李超树】


    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


    李超树模板题

    很简单的好吧,就是一开始忘了对k分类讨论

    用线段树来存储每个区间的相对最优解

    这里用到了一个永久化标记的思想

    这个东西很好啊,每个节点记录区间的相对最优解之后

    直接dfs到叶子节点把路径上经过的所有节点的权值全部取max就可以了

    正确性非常显然,但是怎么维护呢?

    我们假设当前要更新的是一个节点(p_t),那么如果(p_t)的k大于拿来更新的(val)的k

    如果在(mid)(p_t)大于(val),那么显然在([mid+1,r])这个区间里val不可能比(p_t)更优

    所以就把(val)递归到左区间更新

    如果在(mid)(p_t)小于(val),那么在([l,mid])这个区间(p_t)不可能比(val)更优

    所以就把(p_t)递归到右区间,再把(p_t)替换成val就可以了


    //Author: dream_maker
    #include<bits/stdc++.h>
    using namespace std;
    //----------------------------------------------
    //typename
    typedef long long ll;
    //convenient for
    #define fu(a, b, c) for (int a = b; a <= c; ++a)
    #define fd(a, b, c) for (int a = b; a >= c; --a)
    #define fv(a, b) for (int a = 0; a < (signed)b.size(); ++a)
    //inf of different typename
    const int INF_of_int = 1e9;
    const ll INF_of_ll = 1e18;
    //fast read and write
    template <typename T>
    void Read(T &x) {
      bool w = 1;x = 0;
      char c = getchar();
      while (!isdigit(c) && c != '-') c = getchar();
      if (c == '-') w = 0, c = getchar();
      while (isdigit(c)) {
        x = (x<<1) + (x<<3) + c -'0';
        c = getchar();
      }
      if (!w) x = -x;
    }
    template <typename T>
    void Write(T x) {
      if (x < 0) {
        putchar('-');
        x = -x; 
      }
      if (x > 9) Write(x / 10);
      putchar(x % 10 + '0');
    }
    //----------------------------------------------
    #define LD (t << 1)
    #define RD (t << 1 | 1)
    const int MAXN = 5e4;
    struct Line {
      double k, b;
    } p[(MAXN << 2) + 10];
    double calc(int x, Line a) {
      return a.k * (double) x + a.b;
    }
    bool cmp(int x, Line a, Line b) {
      return calc(x, a) > calc(x, b); 
    }
    void modify(int t, int l, int r, Line vl) {
      if (l == r) {
        if (cmp(l, vl, p[t])) p[t] = vl;
        return;
      }
      int mid = (l + r) >> 1;
      if (p[t].k <= vl.k) {
        if (cmp(mid, vl, p[t])) {
          modify(LD, l, mid, p[t]);
          p[t] = vl;
        } else {
          modify(RD, mid + 1, r, vl);
        }
      } else {
        if (cmp(mid, vl, p[t])) {
          modify(RD, mid + 1, r, p[t]);
          p[t] = vl;
        } else {
          modify(LD, l, mid, vl);
        }
      }
    }
    double query(int t, int l, int r, int pos) {
      if (l == r) return calc(pos, p[t]);
      int mid = (l + r) >> 1;
      if (pos <= mid) return max(calc(pos, p[t]), query(LD, l, mid, pos));
      else  return max(calc(pos, p[t]), query(RD, mid + 1, r, pos));
    }
    int n;
    char c[10];
    int main() {
      Read(n);
      while (n--) {
        scanf("%s", c);
        if (c[0] == 'P') {
          Line now;
          scanf("%lf%lf", &now.b, &now.k);
          now.b -= now.k;
          modify(1, 1, MAXN, now);
        } else {
          int x; Read(x);
          printf("%d
    ", (int)query(1, 1, MAXN, x) / 100);
        }
      }
      return 0;
    }
    
  • 相关阅读:
    shell中的 echo命令
    shell中的运算符
    shell中的替换
    shell中的元字符
    springcloud-sleuth的使用
    springcloud-sleuth之zipkun运行和概念介绍
    springcloud-sleuth是什么
    消息总线(bus)和消息驱动(stream)的区别
    springcloud-stream之持久化
    springcloud-stream之消费者重复消费
  • 原文地址:https://www.cnblogs.com/dream-maker-yk/p/9870507.html
Copyright © 2020-2023  润新知