@bzoj - 2388@ 旅行规划

目录

  • @description@
  • @solution@
  • @accepted code@
  • @details@

@description@

请你维护一个序列,支持两种操作:
(1)某个区间 [x, y] 内的数同时加上一个增量 k。
(2)询问某一个区间 [x, y] 中从 1 开始的最大前缀和。

input
第一行给出一个整数 n。n <= 100000。接下来一行 n 个整数表示序列的初始值。
第三行给出一个整数 m,m <= 100000。接下来 m 行每行一个操作。
(1) 0 x y k:表示给区间 [x, y] 同时加上 k。
(2) 1 x y:询问区间 [x, y]。
output
对于每个询问,输出一个整数表示最大前缀和。

sample input
5
1 8 -8 3 -7
3
1 1 5
0 1 3 6
1 2 4
sample output
9
22

@solution@

我们考虑直接维护前缀和序列,则操作(2)就是在查询区间最大值。

而对于操作(1),我们相当于两部分操作:
对于 x <= i <= y,给 i 位置加上 (i-x+1)*k;对于 y < i,给 i 位置加上 (y-x+1)*k。
前一个可以拆成 (-x+1)*k + i*k,是常数 + 系数*位置的形式;后面那个也可以看成这种形式,只是位置前面的系数为 0。

看起来还是不好维护,但是我们可以注意到这样一件事情:对于某一个位置 i,它的值总是形如 k*i + b 的形式。
直线解析式。所以我们考虑用几何方法来维护这种东西。几何方法当然首先想到凸包。

每次操作相当于给区间内所有点的斜率与截距同时加上增量,手算一下会发现这个区间相邻两点之间的斜率也会同时增加 k,这样也就是说这个区间的凸包形状不会变化。

线段树不太好搞(况且这道题时限 50s ),我们考虑使用分块算法来维护凸包。
修改时,散块暴力修改并重构凸包,整块打标记,记录这个区间整体的斜率与截距变化量。
查询时,散块暴力求答案,整块凸包上二分。

时间复杂度 \(O(n\sqrt{n}\log n)\)

@accepted code@

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 100000;
const int BLOCK = 320;
const ll INF = (1ll<<62);
ll sp[BLOCK + 5], b1[MAXN + 5], b2[BLOCK + 5];
int le[BLOCK + 5], ri[BLOCK + 5], num[MAXN + 5];
int stk[MAXN + 5], tp[BLOCK + 5], n, m, bcnt = 0;
ll get_ans(int x) {return sp[num[x]]*x + b1[x] + b2[num[x]];
}
ll query(int x) {int l = le[x], r = tp[x];while( l < r ) {int mid = (l + r) >> 1;if( get_ans(stk[mid]) >= get_ans(stk[mid+1]) ) r = mid;else l = mid + 1;}return get_ans(stk[r]);
}
void push_tag(int x) {for(int i=le[x];i<=ri[x];i++)b1[i] = get_ans(i);sp[x] = b2[x] = 0;
}
void build(int x) {tp[x] = le[x] - 1;for(int i=le[x];i<=ri[x];i++) {while( tp[x] > le[x] && (get_ans(i) - get_ans(stk[tp[x]]))*(stk[tp[x]] - stk[tp[x] - 1]) >= (get_ans(stk[tp[x]])-get_ans(stk[tp[x] - 1]))*(i - stk[tp[x]]) )tp[x]--;stk[++tp[x]] = i;}
}
void init() {for(int i=0;i<n;i++) {if( i % BLOCK == 0 ) {num[i] = (++bcnt);le[num[i]] = ri[num[i]] = i;sp[num[i]] = b2[num[i]] = 0;}else ri[num[i] = bcnt]++;}
}
int main() {scanf("%d", &n); init();for(int i=0;i<n;i++)scanf("%lld", &b1[i]), b1[i] += b1[i-1];for(int i=1;i<=bcnt;i++)build(i);scanf("%d", &m);for(int i=1;i<=m;i++) {int op, x, y; ll k;scanf("%d%d%d", &op, &x, &y);x--, y--;if( op == 0 ) {scanf("%lld", &k);if( num[x] != num[y] ) {push_tag(num[x]), push_tag(num[y]);for(int i=x;i<=ri[num[x]];i++)b1[i] += k*(i-x+1);for(int i=le[num[y]];i<=y;i++)b1[i] += k*(i-x+1);for(int i=y+1;i<=ri[num[y]];i++)b1[i] += k*(y-x+1);build(num[x]), build(num[y]);for(int i=num[x]+1;i<=num[y]-1;i++)sp[i] += k, b2[i] += k*(-x+1);}else {push_tag(num[x]);for(int i=x;i<=y;i++)b1[i] += k*(i-x+1);for(int i=y+1;i<=ri[num[y]];i++)b1[i] += k*(y-x+1);build(num[x]);}for(int i=num[y]+1;i<=bcnt;i++)b2[i] += k*(y-x+1);}else {ll ans = -INF;if( num[x] != num[y] ) {for(int i=x;i<=ri[num[x]];i++)ans = max(ans, get_ans(i));for(int i=le[num[y]];i<=y;i++)ans = max(ans, get_ans(i));for(int i=num[x]+1;i<=num[y]-1;i++)ans = max(ans, query(i));}else {for(int i=x;i<=y;i++)ans = max(ans, get_ans(i));}printf("%lld\n", ans);}}
}

@details@

突然发现这是我第一次写分块?原来我以前从来没写过这种东西?
把分块的左端点右端点以及每个点属于哪个块先预处理出来感觉比较好写。
并且把块的大小设置为常数也是一个不错的懒人做法(虽然想想都知道这样肯定常数大)。

转载于:https://www.cnblogs.com/Tiw-Air-OAO/p/10262494.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/351609.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java与java ee_Java EE 7社区调查结果!

java与java ee在JSR 342下可以继续进行Java EE 7的工作。一切都在顺利进行&#xff0c;Java EE 7现在处于早期草稿审查阶段。 在11月初&#xff0c; Oracle发布了一个有关即将推出的Java EE 7功能的小型社区调查 。 昨天结果公布了。 超过1,100名开发人员参加了调查&#xff0…

浅谈C++中内存分配、函数调用和返回值问题

在谈述函数调用和返回值问题之前&#xff0c;先来看看C中内存分配的问题。 C编译器将计算机内存分为代码区和数据区&#xff0c;很显然&#xff0c;代码区就是存放程序代码&#xff0c;而数据区则是存放程序编译和执行过程出现的变量和常量。数据区又分为静态数据区、动态数据区…

dataguard从库数据库丢失恢复例子(模拟所有的控制文件)

1.退出日志应用模式[oraclelocalhost ~]$ sqlplus /nolog SQL*Plus: Release 11.2.0.4.0 Production on Mon Jan 14 16:09:16 2019 Copyright (c) 1982, 2013, Oracle. All rights reserved. SQL> connect / as sysdbaConnected.SQL> alter database recover managed sta…

python教程自带数据库_python教程自带数据库 | Python学哪个数据库

python使用数据库增条数据import pymysql#返回Connection#host"localhost"con pymysql.connect(host"192.168.31.28",port3306,user"atguigu",password"atguigu",db"atguigudb",charset"utf8")#返回cursor对象cu…

Java SE 8新功能介绍:使用新的DateTime API计算时间跨度

使用Java SE 8新的DateTime API JSR 310…可以实现更清晰&#xff0c;可读且功能强大的编码。 Java SE 8&#xff0c;JSR 310 在上一篇文章“ 使用Streams API处理集合 ”中&#xff1b; 我已深入探讨和探索如何使用流遍历集合&#xff0c;如何从集合和数组创建流以及最终汇总…

使用VS2012内建的C++测试架构进行单元测试

前言 在软件开发的过程中&#xff0c;单元测试(Unit testing)是一个重要的coding步骤&#xff0c;可以让你的程序代码质量大幅提升、协助你进行良好的程序架构设计&#xff0c;单元测试是针对程序单元(软件设计的最小单位)来进行正确性检验的测试工作&#xff0c;在程序化编程中…

【博 客 文 章】

1、C#中的Explicit和Implicit转载于:https://www.cnblogs.com/kikyoqiang/p/10270416.html

sql intersect mysql_SQL INTERSECT子句

SQL INTERSECT子句/操作符用于合并两个SELECT语句&#xff0c;但只从第一个SELECT语句返回完全相同于第二个SELECT语句结果的所有行。这意味着INTERSECT是由两个SELECT语句返回相同的行(唯一)。正如使用UNION操作&#xff0c;同样的规则可使用在INTERSECT运算符。 但MySQL不支持…

vs2010下release版本调试设置

设置在Release模式下调试的方法&#xff1a; 1.工程项目上右键 -> 属性 2.c -> 常规 -〉调试信息格式 选 程序数据库(/Zi)或(/ZI), 注意&#xff1a;如果是库的话&#xff0c;只能(Zi) 3.c -> 优化 -〉优化 选 禁止&#xff08;/Od&#xff09; 4.连接…

控制反转 java_控制反转( Ioc)快速入门

2.1 什么是控制反转(IOC&#xff1a;Inverse of Control)IOC反转控制&#xff0c;实际上就是将对象的创建权交给了Spring&#xff0c;程序员无需自己手动实例化对象。可以看出来工厂的作用就是用来解耦合的&#xff0c;而在使用spring的过程中&#xff0c;spring就是充当这个工…

spring 工作流引擎_带Spring的简单工作流引擎

spring 工作流引擎几个月前&#xff0c;在处理一个公司项目时&#xff0c;我们需要开发REST服务&#xff0c;该服务用于根据客户端应用程序发送的数据发送电子邮件。 在开发此服务期间&#xff0c;我们决定创建简单的工作流引擎&#xff0c;该引擎将为发送电子邮件收费&#xf…

如何成为一个牛逼的C/C++程序员? (仔细阅读)

这个题目的噱头太大&#xff0c;要真的写起来&#xff0c; 足够写一本书了。 本人是过来人&#xff0c; 结合自身的体会和大家交流一下&#xff0c;希望新人能少走弯路。 每个人的情况不一样&#xff0c;我下面的描述可能并不适合每一个看到这篇文章的人。 一、C/C语言 如果你的…

java 两个字段排序,如何在Java中按两个字段排序?

I have array of objects person (int age; String name;).How can I sort this array alphabetically by name and then by age?Which algorithm would you use for this ?解决方案You can use Collections.sort as follows:private static void order(List persons) {Colle…

数据结构java语言描述朱战立_数据结构——树(Java语言描述)

树根:rootNode. 树只有一个树根。节点:Node. 树上的所有节点。子节点数组:Node[]. 数组代表每个节点的所有子节点父节点:parentNode. 每个节点只有一个父节点。2. Node为Tree中的内部类parent &#xff1a;指向父节点的引用childern: 孩子数组&#xff0c;存储该节点的所有子节…

centos7.4进入单用户模式

centos7.4进入单用户模式 1 - 在启动grub菜单&#xff0c;选择编辑选项启动2 - 按键盘e键&#xff0c;来进入编辑界面 3 - 找到Linux 16的那一行&#xff0c;将ro改为rw init/sysroot/bin/sh 4 - 现在按下 Controlx &#xff0c;使用单用户模式启动 5 - 现在&#xff0c;可以使…

判断某程序是64位还是32位

1. 用代码判断本身if (IntPtr.Size 4) {// 32-bit}else if (IntPtr.Size 8){// 64-bit}2. 用代码判断正在运行的其他进程http://stackoverflow.com/questions/1953377/how-to-know-a-process-is-32-bit-or-64-bit-programmatically3. 不用代码判断任意exe&#xff0c;看第二个…

MySQL 中 NULLIF 、IFNULL、IF 的用法和区别

在 MySQL 中&#xff0c;NULLIF、IFNULL 和 IF 是用于处理 NULL 值的三种不同的函数。 1. NULLIF 函数 NULLIF 函数用于比较两个表达式&#xff0c;如果它们的值相等&#xff0c;则返回 NULL&#xff0c;否则返回第一个表达式的值。语法如下&#xff1a; NULLIF(expr1, expr2…

32和64位jvm_我应该使用32位还是64位JVM?

32和64位jvm这是我在企业软件开发生涯中多次遇到的问题。 我不得不每隔一段时间就提供有关配置特定新环境的建议。 而且&#xff0c;很多时候&#xff0c;手头的问题与“我应该使用32位或64位JVM”有关。 老实说&#xff0c;一开始我只是掷硬币。 而不是给出合理的答案。 &…

spring java code配置_Spring-09-使用Java的方式配置Spring

9. 使用Java的方式配置Spring我们现在要完全不使用Spring的xml配置&#xff0c;全权使用Java来配置Spring&#xff01;JavaConfig是Spring的一个子项目&#xff0c;在Spring4之后&#xff0c;他成为了一个核心功能。实体类&#xff1a;public class User {private String name;…

pythone函数基础(11)读,写,修改EXCEL

#读EXCEL需要导入xlrd模块---在python控制台pip install xlrd模块import xlrdbook xlrd.open_workbook(stu3.xls)sheet book.sheet_by_index(0)# sheet book.sheet_by_name(sheet1)# print(sheet.cell(0,0).value)#获取指定单元格的内容# print(sheet.cell(1,0).value)# pri…