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$天 接下来 ...
随机推荐
- wampserver发布详解
以下为wampserver发布php并绑定域名的操作 1 在“httpd.conf”文件中查找:Include conf/extra/httpd-vhosts.conf,去掉前面的注释# 2 打开ap ...
- Android字符设备驱动开发基于高通msm8916【原创 】
本人才疏浅学,写一篇文档总结自己在msm8916平台上移植自己编写的简单的字符设备驱动开发的整个流程.这个小项目的主要功能是开发一个简单的APP,APP通过JNI去调用位于kernel的字符设备驱动. ...
- vi编辑器使用方法(最详细)
vi编辑器是所有Unix及Linux系统下标准的编辑器,它的强大不逊色于任何最新的文本编辑器,这里只是简单地介绍一下它的用法和一小部分指令.由于对Unix及Linux系统的任何版本,vi编辑器是完全相 ...
- 修改织梦DedeCms文章页默认title的方法
<title>{dede:field.title/}_{dede:field name='typeid' runphp='yes'}$id=@me;global $dsql;$sql=&q ...
- matlab的一个疑问?
把逻辑值放入一个已知矩阵,为啥结果是:真就取矩阵的值,假就不取值? K>> aaaa=randi(10,10,2) aaaa = 6 3 10 4 6 7 5 2 6 3 8 2 1 2 ...
- 团队作业第5周——测试与发布(Alpha版本)
1.发现的bug a.同时按下和蛇前进方向相反的键和垂直方向的任意一个键贪吃蛇会死亡(比如贪吃蛇向右行走,同时按左上或左下都会game over) b.刷新的苹果会在蛇身上出现 暂时还没能力修复,以后 ...
- L95
The children squealed with delight when they saw the puppy.The signal will be converted into digital ...
- win7 jenkins 修改主目录
1.安装tomcat 2.下载Jenkins.war包,把Jenkins.war放在D:\01Install\tomcat\webapps目录下,启动tomcat
- COM对象创建过程
在客户端需要调用COM组件时,通常调用windowAPI函数: STDAPI CoCreateInstance( REFCLSID rclsid, //创建的Com对象的类标识符(CLSID) LPU ...
- Laravel的三种安装方法总结
Laravel号称巨匠级PHP框架,越来越多的PHPer选择它作为开发框架,作为一个Laravel初学者相信很多人向我一样被安装挡在了门外.所以今天结合文档和自己的学习经历总结一下Laravel的安装 ...