【CodeForces】91E Igloo Skyscraper

本文介绍了一种基于线段树原理的区间查询优化算法,通过将数据分块并维护每块内直线的单调性来实现快速查询。适用于高楼高度随时间变化的问题,采用离线处理方式,整体时间复杂度为O(nsqrt(n))。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:

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 }

转载于:https://www.cnblogs.com/DrunBee/archive/2012/08/28/2660648.html

资源下载链接为: https://pan.quark.cn/s/22ca96b7bd39 在当今的软件开发领域,自动化构建与发布是提升开发效率和项目质量的关键环节。Jenkins Pipeline作为一种强大的自动化工具,能够有效助力Java项目的快速构建、测试及部署。本文将详细介绍如何利用Jenkins Pipeline实现Java项目的自动化构建与发布。 Jenkins Pipeline简介 Jenkins Pipeline是运行在Jenkins上的一套工作流框架,它将原本分散在单个或多个节点上独立运行的任务串联起来,实现复杂流程的编排与可视化。它是Jenkins 2.X的核心特性之一,推动了Jenkins从持续集成(CI)向持续交付(CD)及DevOps的转变。 创建Pipeline项目 要使用Jenkins Pipeline自动化构建发布Java项目,首先需要创建Pipeline项目。具体步骤如下: 登录Jenkins,点击“新建项”,选择“Pipeline”。 输入项目名称和描述,点击“确定”。 在Pipeline脚本中定义项目字典、发版脚本和预发布脚本。 编写Pipeline脚本 Pipeline脚本是Jenkins Pipeline的核心,用于定义自动化构建和发布的流程。以下是一个简单的Pipeline脚本示例: 在上述脚本中,定义了四个阶段:Checkout、Build、Push package和Deploy/Rollback。每个阶段都可以根据实际需求进行配置和调整。 通过Jenkins Pipeline自动化构建发布Java项目,可以显著提升开发效率和项目质量。借助Pipeline,我们能够轻松实现自动化构建、测试和部署,从而提高项目的整体质量和可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值