bzoj2388(分块 凸包)
好像没有什么高级数据结构能够很高效地实现这个东西;
那就上万能的分块,我们用一些数形结合的思想,把下标看成横坐标,前缀和的值看成纵坐标;
给区间内每个数都加k相当于相邻两点的斜率都加上k;
这种东西我们可以考虑用凸包来维护,因为根据凸包的几何意义,显然最值点在凸包上;
根据凸包的构造方式,相邻两点的斜率都加上k,在凸包中的点集是不变的,这就很好了;
每次二分出斜率为零的地方就好了;
#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll inf=1e16;
const int maxn=;
int bo,tu[][],siz[],pos[maxn];
//fir是他被包含在某一个区间加中时,对这个块的贡献;arr时不包含;d是这个块被区间加了多少;
int m,sta[],top,n,cnt;
ll h[maxn],fir[],arr[],d[];
inline double xl(int x,int y){return double(h[y]-h[x])/double(y-x);}
//good
void build(int x){//在x这一块中构造凸包
int be=(x-)*bo+,en=min(x*bo,n);
top=;sta[++top]=be;
for(int i=be+;i<=en;++i){
while(top>=&&xl(sta[top-],sta[top])<xl(sta[top-],i))top--;
sta[++top]=i;
}
sta[]=;sta[top+]=n+;
siz[x]=top;
for(int i=;i<=top+;++i)tu[x][i]=sta[i];
}
//
//good
void pushdown(int x){
ll tmp=fir[x];
int be=(x-)*bo+,en=min(x*bo,n);
for(int i=be;i<=en;++i){
h[i]+=tmp;tmp+=d[x];h[i]+=arr[x];
}
fir[x]=d[x]=arr[x]=;
}
//
//good
ll cal(int p){
if(p==||p==n+)return -inf;
int x=pos[p];
return h[p]+fir[x]+d[x]*(p-((x-)*bo+))+arr[x];
}
//
//good
ll fin(int x){
int l=,r=siz[x];
ll h1,h2,h3;
while(l<=r){
int mid=(l+r)>>;
h1=cal(tu[x][mid-]),h2=cal(tu[x][mid]),h3=cal(tu[x][mid+]);
if(h1<h2&&h2<h3)l=mid+;
else {
if(h1>h2&&h2>h3)r=mid-;
else{return h2;}
}
}
}
//
int main(){
cin>>n;
bo=(int)sqrt(n);
cnt=(n-)/bo+;
h[]=h[n+]=-inf;
for(int i=;i<=n;++i){
scanf("%lld",&h[i]);
}
for(int i=;i<=n;++i){
h[i]+=h[i-];
}
for(int i=;i<=n;++i){
pos[i]=(i-)/bo+;
}
for(int i=;i<=cnt;++i)build(i);
cin>>m;
int op,x,y,l,r;
ll k,tmp,ans;
for(int i=;i<=m;++i){
scanf("%d%d%d",&op,&x,&y);
if(!op){
scanf("%lld",&k);
l=pos[x];r=pos[y];
tmp=k*(l*bo+-x+);
for(int i=l+;i<=r-;++i){
fir[i]+=tmp;d[i]+=k;
tmp+=bo*k;
}
pushdown(l);
tmp=k;
for(int i=x;i<=min(y,min(l*bo,n));++i)
h[i]+=tmp,tmp+=k;
build(l);
pushdown(r);
if(l!=r){
tmp=k*((r-)*bo-x+);
for(int i=(r-)*bo+;i<=y;++i){
h[i]+=tmp;tmp+=k;
}
}
tmp=k*(y-x+);
for(int i=y+;i<=min(r*bo,n);++i)h[i]+=tmp;
build(r);
for(int i=r+;i<=cnt;++i)arr[i]+=tmp;
}
else{
l=pos[x];r=pos[y];ans=-inf;
for(int i=l+;i<r;++i)
ans=max(ans,fin(i));
for(int i=x;i<=min(y,min(l*bo,n));++i){
ans=max(ans,cal(i));
}
if(l!=r){
for(int i=(r-)*bo+;i<=y;++i){
ans=max(ans,cal(i));
}
}
printf("%lld\n",ans);
}
}
system("pause");
return ;
}
bzoj2388(分块 凸包)的更多相关文章
- 2019.01.20 bzoj2388: 旅行规划(分块+凸包)
传送门 分块好题. 题意:维护区间加,维护区间前缀和的最大值(前缀和指从1开始的). 思路: 考虑分块维护答案. 我们把每个点看成(i,sumi)(i,sum_i)(i,sumi)答案一定会在凸包上 ...
- BZOJ2388:旅行规划(travel)——分块凸包
题目 OIVillage 是一个风景秀美的乡村,为了更好的利用当地的旅游资源,吸引游客,推动经济发展,xkszltl 决定修建了一条铁路将当地 $n$ 个最著名的经典连接起来,让游客可以通过火车从铁路 ...
- BZOJ2388: 旅行规划(分块 凸包)
题意 题目链接 Sol 直接挂队爷的题解了 分块题好难调啊qwq #include<bits/stdc++.h> #define LL long long using namespace ...
- BZOJ 2388: 旅行规划 [分块 凸包 等差数列]
传送门 题意: 区间加和询问一段区间内整体前缀和的最大值 刚才还在想做完这道题做一道区间加等差数列结果发现这道就是.... 唯一的不同在于前缀和一段区间加上等差数列后,区间后面也要加上一个常数!!! ...
- 「BZOJ2388」旅行规划
传送门 分块+凸包 求出前缀和数组s 对于l~r加上k,相当于s[l]~s[r]加上一个首项为k,公差为k的等差数列.r~n加上k*(r-l+1). 分块之后对每一块维护两个标记,一个记录它加的等差数 ...
- 旅行规划(travel)
题目描述 OIVillage 是一个风景秀美的乡村,为了更好的利用当地的旅游资源,吸引游客,推动经济发展,xkszltl 决定修建了一条铁路将当地 nnn 个最著名的经典连接起来,让游客可以通过火车从 ...
- ZROI 19.07.28 序列数据结构/jk
写在前面 dls:"我不会数据结构,但是APIO的数据结构场我写了,还是蛮简单的." T1 CF643G Sol: 有一个\(O(n\log^2n)\)的做法:假设将区间排好序,取 ...
- 【bzoj5089】最大连续子段和 分块+单调栈维护凸包
题目描述 给出一个长度为 n 的序列,要求支持如下两种操作: A l r x :将 [l,r] 区间内的所有数加上 x : Q l r : 询问 [l,r] 区间的最大连续子段和. 其中,一 ...
- CF573E Bear and Bowling 贪心、分块、凸包
传送门 题解搬运工++ 先证明一个贪心做法的正确性:做以下操作若干次,每一次考虑选择没有被选到答案序列中的数加入到答案序列中对答案的贡献,设第\(i\)个位置的贡献为\(V_i\),如果最大的贡献小于 ...
随机推荐
- jquery滚动事件
滚动到一定高度: $(window).scroll(function(){ var scrollTop = $(document).scrollTop(); && scrollTop ...
- 使用 gitbook 写东西
会了markdown 不会用gitbook怎么可以呢 先安装 npm install gitbook -g npm install gitbook-cli -g cli使用代码是客户端的意思,要牢记 ...
- linux操作系统-两台linux服务器SSH免密码登录
A为本地主机(即用于控制其他主机的机器) ; B为远程主机(即被控制的机器Server), ip为192.168.100.247 ; A和B的系统都是Linux 在A上的命令 # ssh-keyg ...
- HTML与XHTML的差别(转自)http://jingyan.baidu.com/article/597035521c31ed8fc007400a.html
HTML与XHTML之间的差别,粗略可以分为两大类比较:一个是功能上的差别,另外是书写习惯的差别.关于功能上的差别,主要是XHTML可兼容各大浏览器.手机以及PDA,并且浏览器也能快速正确地编译网页. ...
- (转)无效的CurrentPageIndex 值。它必须大于等于0 且小于PageCount 解决方案
第一种: 当以某种条件来查询的时候 其中的结果是以一个结果为条件的datagrid分页 采用字查询到条件下加入如下代码: [c-sharp] view plaincopyprint? protecte ...
- UIButton 设置图片文字垂直居中排列
#pragma mark 按钮图片文字垂直居中排列 -(void)setButtonContentCenter:(UIButton *)button { CGSize imgViewSize,titl ...
- UISwitch开关控件属性介绍以及获取开关状态并做出响应
(1)UISwitch的大小也是固定的,不随我们frame设置的大小改变:也是裁剪成圆角的,设置背景就露马脚发现背景是矩形. (2)UISwitch的背景图片设置无效,即我们只能设置颜色,不能用图片当 ...
- AppStore企业账号打包发布APP流程详解
一.通过企业账号申请证书 1 Certificate Signing Request (CSR)文件 在Mac系统中进入“钥匙串访问”,选择“钥匙串访问”-“证书助理”-“从证书颁发机构请求证书…”, ...
- 201621123008 《Java程序设计》第14周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结与数据库相关内容. 2. 使用数据库技术改造你的系统 2.1 简述如何使用数据库技术改造你的系统.要建立什么表?截图你的表设计. 分 ...
- python——处理xls表格
因为工作需要,现有一个运营商导出的xls固定电话话费账单. 账单比较详细,而我最终需要的数据只有那个号码这个月用了多少话费的统计结果. 当年没有好好学office,以致于无从下手.泪奔/(ㄒoㄒ)/~ ...