BZOJ2388:旅行规划(travel)——分块凸包
题目
OIVillage 是一个风景秀美的乡村,为了更好的利用当地的旅游资源,吸引游客,推动经济发展,xkszltl 决定修建了一条铁路将当地 $n$ 个最著名的经典连接起来,让游客可以通过火车从铁路起点( $1$ 号景点)出发,依次游览每个景区。为了更好的评价这条铁路,xkszltl 为每一个景区都赋予了一个美观度,而一条旅行路径的价值就是它所经过的景区的美观度之和。不过,随着天气与季节的变化,某些景点的美观度也会发生变化。
xkszltl 希望为每位旅客提供最佳的旅行指导,但是由于游客的时间有限,不一定能游览全部景区,然而他们也不希望旅途过于短暂,所以每个游客都希望能在某一个区间内的车站结束旅程,而 xkszltl 的任务就是为他们选择一个终点使得旅行线路的价值最大。可是当地的景点与前来观光的旅客实在是太多了,xkszltl 无法及时完成任务,于是找到了准备虐杀 NOI2019 的你,希望你能帮助他完成这个艰巨的任务。
【输入格式】
第一行给出一个整数 $n$,接下来一行给出 $n$ 的景区的初始美观度。
第三行给出一个整数 $m$,接下来 $m$ 行每行为一条指令:
$1.~~~0~x~y~k$:表示将 $x$ 到 $y$ 这段铁路边上的景区的美观度加上 $k$;
$2.~~~1~x~y$:表示有一名旅客想要在 $x$ 到 $y$ 这段(含 $x$ 与 $y$ )中的某一站下车,你需要告诉他最大的旅行价值。
【输出格式】
对于每个询问,输出一个整数表示最大的旅行价值。
【样例输入】
5
1 8 -8 3 -7
3
1 1 5
0 1 3 6
1 2 4
【样例输出】
9
22
【数据范围与提示】
对于 $20\%$ 的数据,$n,m≤3000$;
对于 $40\%$ 的数据,$n,m≤30000$;
对于 $50\%$ 的数据,$n,m≤50000$;
另外 $20\%$ 的数据,$n,m≤100000$,修改操作 $≤20$;
对于 $100\%$ 的数据,$n,m≤100000$。
题解
无力吐槽这组超级强(孱弱)的样例(过了样例还是调出了 INF 个错)
题目求得是区间最大前缀和,带区间加值操作
然后发现线段树无法在 $ O(\log n) $ 的时间内维护区间加上一次函数后的最大值
考虑分块维护最大值
记 $ sum(i) $ 表示前缀和,$ num(i) $ 表示块 $ i $ 加上的一次函数,$ d(i) $ 表示这个块需要加上的常数,
那么 $ sum(i)=num(i)\times i +d(i) $
发现最大值形如 $ y=kx+b $,然后就可以在块上维护一个凸包
当块上加一个一次函数时,凸包的点是不会改变的,那么每次加值时就只要每次重构左右两边的两个凸包即可
查询时只要在每一个块的凸包上二分即可
时间:修改时$ O(\sqrt{n}) $,查询时 $ O(\sqrt{n}) $,所以总时间 $ O(m\sqrt{n}\log n) $
代码
#include<bits/stdc++.h>
#define LL long long
#define db double
#define _(d) while(d(isdigit(ch=getchar())))
using namespace std;
int R(){
int x;bool f=;char ch;_(!)if(ch=='-')f=;x=ch^;
_()x=(x<<)+(x<<)+(ch^);return f?x:-x;}
const int N=1e5+,M=;
int n,m,a[N],Sz,Mx,p[N],sz[M],tb[M][M];
LL w[N],num[N],f[N],d[N];
db getK(int i,int j){return (db)(w[i]-w[j])/(db)(i-j);}
void update(int x){
int l=(x-)*Sz+,r=min(x*Sz,n),tot=;
p[++tot]=l;
for(int i=l+;i<=r;i++){
while(tot>&&getK(p[tot],p[tot-])<getK(p[tot-],i))
tot--;
p[++tot]=i;
}
sz[x]=tot;
for(int i=;i<=tot;i++)tb[x][i]=p[i];
return;
}
void pushdown(int x){
LL o=num[x];
for(int i=(x-)*Sz+;i<=min(x*Sz,n);i++)
o+=d[x],w[i]+=o;
num[x]=d[x]=;
return;
}
void change(int l,int r,int k){
int x=a[l],y=a[r];LL o=;
pushdown(x);
for(int i=l;i<=min(x*Sz,r);i++)
o+=k,w[i]+=o;
update(x);
for(int i=x+;i<y;i++)
num[i]+=o,d[i]+=k,o+=1ll*Sz*k;
if(x!=y){
pushdown(y);
for(int i=(y-)*Sz+;i<=r;i++)
o+=k,w[i]+=o;
}
o=(r-l+)*k;
for(int i=r+;i<=min(n,y*Sz);i++)w[i]+=o;
update(y);
for(int i=y+;i<=Mx;i++)num[i]+=o;
return;
}
LL find(int i){
if(!i||i>n)return (LL)-2e18;
return (w[i]+num[a[i]]+d[a[i]]*(i-(a[i]-)*Sz));
}
LL work(int x){
int l=,r=sz[x];
while(l<=r){
int mid=(l+r)>>;
LL t1=find(tb[x][mid-]);
LL t2=find(tb[x][mid]);
LL t3=find(tb[x][mid+]);
if (t1<t2 && t2<t3) l=mid+;
else if (t1>t2 && t2>t3) r=mid-;
else return t2;
}
return l;
}
LL query(int l,int r){
int x=a[l],y=a[r];LL ans=-2e18;
for(int i=x+;i<y;i++)
ans=max(ans,work(i));
for(int i=l;i<=min(x*Sz,r);i++)
ans=max(ans,find(i));
if(x!=y)
for(int i=(y-)*Sz+;i<=r;i++)
ans=max(ans,find(i));
return ans;
}
int main(){
n=R(),Sz=sqrt(n);
for(int i=;i<=n;i++)
w[i]=w[i-]+R(),a[i]=(i-)/Sz+;
Mx=a[n],m=R();
for(int i=;i<=Mx;i++)update(i);
for(int i=;i<=m;i++){
int op=R(),x=R(),y=R(),k;
if(op==)printf("%lld\n",query(x,y));
if(!op)k=R(),change(x,y,k);
}
return ;
}
BZOJ2388:旅行规划(travel)——分块凸包的更多相关文章
- 2019.01.20 bzoj2388: 旅行规划(分块+凸包)
传送门 分块好题. 题意:维护区间加,维护区间前缀和的最大值(前缀和指从1开始的). 思路: 考虑分块维护答案. 我们把每个点看成(i,sumi)(i,sum_i)(i,sumi)答案一定会在凸包上 ...
- BZOJ2388: 旅行规划(分块 凸包)
题意 题目链接 Sol 直接挂队爷的题解了 分块题好难调啊qwq #include<bits/stdc++.h> #define LL long long using namespace ...
- BZOJ2388 : 旅行规划
考虑分块,每块维护两个标记$ts,td$. 那么对于块中一个位置$i$,它的实际值为$i\times td+ts+v_i$. 修改的时候,对于整块,直接打标记,对于零散的暴力修改,然后重构凸壳,时间复 ...
- 旅行规划(travel)
题目描述 OIVillage 是一个风景秀美的乡村,为了更好的利用当地的旅游资源,吸引游客,推动经济发展,xkszltl 决定修建了一条铁路将当地 nnn 个最著名的经典连接起来,让游客可以通过火车从 ...
- 「BZOJ2388」旅行规划
传送门 分块+凸包 求出前缀和数组s 对于l~r加上k,相当于s[l]~s[r]加上一个首项为k,公差为k的等差数列.r~n加上k*(r-l+1). 分块之后对每一块维护两个标记,一个记录它加的等差数 ...
- BZOJ 2388: 旅行规划 [分块 凸包 等差数列]
传送门 题意: 区间加和询问一段区间内整体前缀和的最大值 刚才还在想做完这道题做一道区间加等差数列结果发现这道就是.... 唯一的不同在于前缀和一段区间加上等差数列后,区间后面也要加上一个常数!!! ...
- bzoj2388(分块 凸包)
好像没有什么高级数据结构能够很高效地实现这个东西: 那就上万能的分块,我们用一些数形结合的思想,把下标看成横坐标,前缀和的值看成纵坐标: 给区间内每个数都加k相当于相邻两点的斜率都加上k: 这种东西我 ...
- @bzoj - 2388@ 旅行规划
目录 @description@ @solution@ @accepted code@ @details@ @description@ 请你维护一个序列,支持两种操作: (1)某个区间 [x, y] ...
- [CSP-S模拟测试]:旅行计划(分块+DP)
题目传送门(内部题83) 输入格式 第一行两个整数$n,m$ 接下来$m$行,每行三个整数,$u,v,w$,表示从$u$到$v$有一条权值为$w$的边 接下来一行有一个整数$q$,表示$q$天 接下来 ...
随机推荐
- 【linux】自动删除7天前的文件
下面的脚本是删除/home目录下7天前的文件 #!/bin/bash -exec rm -f {} \; 把这个脚本保存在/tmp目录下,命名为:clearfile.sh 加入计划任务 crontab ...
- Machine Learning No.2: Linear Regression with Multiple Variables
1. notation: n = number of features x(i) = input (features) of ith training example = value of feat ...
- 《CSS权威指南(第三版)》---第七章 基本视觉格式化
主要知识记录: 1.给一个元素指定内容区宽度,如果设置了内边距,边框和外边距,这些因素都会影响CSS的width属性. 2.在水平格式化的7个属性中,width,margin-left,margin- ...
- js中得~~是什么意思/JS按位非(~)运算符与~~运算符的理解分析
其实是一种利用符号进行的类型转换,转换成数字类型 ~~true == 1 ~~false == 0 ~~"" == 0 ~~[] == 0 ~~undefined ==0 ~~!u ...
- oracle_sql的用法?
本机连接oracle 数据库?打开cmd ----> 不同的用户有不同的用户名密码 ----> sqlplus scott/tiger(安装oracle数据库预留的用户)---- 回车 - ...
- TYOI 1015 Game:博弈 结论【步数之和的奇偶性】
题意: 明明和亮亮在玩一个游戏. 桌面上一行有n个格子,一些格子中放着棋子. 明明和亮亮轮流选择如下方式中的一种移动棋子(图示中o表示棋子,*表示空着的格子): (1)当一枚棋子的右边是空格子的话,可 ...
- 分享知识-快乐自己:intellij Idea报错Could not autowire. No beans of...
intellig idea 使用@Resource或者@Autowire报错,出现红色波浪线: 虽然不影响使用,但是看着很不爽,所以还是解决了下: 报错提示: Could not autowire. ...
- Java编程思想(18~22)
第18章 Java I/O系统 18.1 File 类 18.1.1 目录列表器 18.1.2 目录实用工具 18.1.3 目录的检查及创建18.2 输入和输出 在Java 1.0中类库的设计者限定于 ...
- ThreadPoolExecutor线程池进阶使用
一.简介 线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为: ThreadPoolExecutor(int corePoolSize, int ...
- 无言以队Alpha阶段项目复审
小组的名字和链接 优点 缺点,bug报告 (至少140字) 最终名次 (无并列) 甜美女孩 http://www.cnblogs.com/serendipity-zeng/p/9937832.html ...