• 【CodeForces】91E Igloo Skyscraper


    题意:

    n幢摩天大楼,第i幢初始高度为a[i],每个单位时间增长b[i]。

    询问区间[x,y]的大楼在t时刻的最大高度。

    虽然是区间查询,线段树不会搞。

    先读入询问,对时间非降排序,离线搞是很显然的。

    分成sqrt(n)块,在区间内的每块在常数时间内得到答案,两端暴力答案。

    高度y[i]=a[i]+b[i]*t,是直线方程。所以每块在常数时间得到答案,就要维护每块直线的单调性,剔除不影响答案的直线。

    由于块内答案是递增的,所以直线的斜率也是递增的。所以对每块的直线斜率非降排序。

    设有k1,k2,k3三条直线,且斜率递增,若k1与k2的交点在k3的下方,那么k2显然是多余的。

    纸上yy一下,比较时把除法化为乘法,类似求凸包的思想就可以做到的。

    总复杂度 O(nsqrt(n))。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<cmath>
      4 #include<algorithm>
      5 #include<vector>
      6 typedef long long LL;
      7 #define MAXN 100010
      8 #define MAXM 320
      9 #define EPS 1e-8
     10 using namespace std;
     11 int n, block;
     12 struct node {
     13     int pos, high, inc;
     14 };
     15 struct seg {
     16     int pos, x, y, t;
     17 };
     18 node a[MAXN];
     19 seg p[MAXN];
     20 vector<node> b[MAXM];
     21 int pt[MAXM], ans[MAXN];
     22 inline bool cmp1(seg a, seg b) {
     23     return a.t < b.t;
     24 }
     25 inline bool cmp2(node a, node b) {
     26     return a.inc < b.inc;
     27 }
     28 void Init() {
     29     int i;
     30     memset(pt, 0, sizeof(pt));
     31     block = (int) (ceil(sqrt((double) n)) + EPS);
     32     for (i = 0; i < block; i++)
     33         b[i].clear();
     34 }
     35 inline bool Delete(LL a0, LL b0, LL a1, LL b1, LL a2, LL b2) {
     36     return b0 * a1 - a0 * b1 <= a2 * (b0 - b1) + b2 * (a1 - a0);
     37 }
     38 void Increase() {
     39     int i, j, k;
     40     vector<node> tmp;
     41     for (i = 0; i < block; i++) {
     42         tmp.clear();
     43         for (j = 0; j < (int) b[i].size(); j++)
     44             tmp.push_back(b[i][j]);
     45         b[i].clear();
     46         sort(tmp.begin(), tmp.end(), cmp2);
     47         for (j = 0; j < (int) tmp.size(); j++) {
     48             while (b[i].size() > 1) {
     49                 k = (int) b[i].size() - 1;
     50                 if (Delete(b[i][k].high, b[i][k].inc, b[i][k - 1].high,
     51                         b[i][k - 1].inc, tmp[j].high, tmp[j].inc))
     52                     b[i].pop_back();
     53                 else
     54                     break;
     55             }
     56             b[i].push_back(tmp[j]);
     57         }
     58     }
     59 }
     60 int Query(int x, int y, int t) {
     61     LL res, tmp;
     62     int pos, nd, p, q, i;
     63     p = x / block;
     64     q = y / block;
     65     res = 0;
     66     if (p == q) {
     67         for (i = x; i <= y; i++) {
     68             tmp = (LL) a[i].inc * t + a[i].high;
     69             if (tmp > res) {
     70                 res = tmp;
     71                 pos = i;
     72             }
     73         }
     74     } else {
     75         if (x % block) {
     76             for (nd = min(p * block + block, n); x < nd; x++) {
     77                 tmp = (LL) a[x].inc * t + a[x].high;
     78                 if (tmp > res) {
     79                     res = tmp;
     80                     pos = x;
     81                 }
     82             }
     83         }
     84         if (y % block != block - 1) {
     85             for (nd = max(q * block, 1); y >= nd; y--) {
     86                 tmp = (LL) a[y].inc * t + a[y].high;
     87                 if (tmp > res) {
     88                     res = tmp;
     89                     pos = y;
     90                 }
     91             }
     92         }
     93         for (p = x / block; x <= y; x += block, p++) {
     94             while (pt[p] < (int) b[p].size() - 1) {
     95                 if ((LL) b[p][pt[p]].inc * t + b[p][pt[p]].high
     96                         <= (LL) b[p][pt[p] + 1].inc * t + b[p][pt[p] + 1].high)
     97                     pt[p]++;
     98                 else
     99                     break;
    100             }
    101             tmp = (LL) b[p][pt[p]].inc * t + b[p][pt[p]].high;
    102             if (tmp > res) {
    103                 res = tmp;
    104                 pos = b[p][pt[p]].pos;
    105             }
    106         }
    107     }
    108     return pos;
    109 }
    110 int main() {
    111     int i, q;
    112     while (~scanf("%d%d", &n, &q)) {
    113         Init();
    114         for (i = 1; i <= n; i++) {
    115             scanf("%d%d", &a[i].high, &a[i].inc);
    116             a[i].pos = i;
    117             b[i / block].push_back(a[i]);
    118         }
    119         for (i = 0; i < q; i++) {
    120             scanf("%d%d%d", &p[i].x, &p[i].y, &p[i].t);
    121             p[i].pos = i;
    122         }
    123         sort(p, p + q, cmp1);
    124         Increase();
    125         for (i = 0; i < q; i++)
    126             ans[p[i].pos] = Query(p[i].x, p[i].y, p[i].t);
    127         for (i = 0; i < q; i++)
    128             printf("%d\n", ans[i]);
    129     }
    130     return 0;
    131 }
  • 相关阅读:
    SQL如何获取上一条..下一条..首尾记录
    PHP判断浏览器类型的代码
    html命名规范
    使用JavaScript JS 获取label for 标签的值和for值
    PNG透明兼容IE6的几种方法
    冉茂锋同学去上课了
    十一戒,自勉
    语录
    CreateThread最后还是调用的ntdll.dll里面的ZwCreateThread
    InitializeObjectAttributes
  • 原文地址:https://www.cnblogs.com/DrunBee/p/2660648.html
Copyright © 2020-2023  润新知