BZOJ 2388--旅行规划(分块单调栈二分)
2388: 旅行规划
Time Limit: 50 Sec Memory Limit: 128 MB
Submit: 405 Solved: 118
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
1 8 -8 3 -7
3
1 1 5
0 1 3 6
1 2 4
Sample Output
22
HINT
对于100%的数据,n,m≤100000。
题目链接:
http://www.lydsy.com/JudgeOnline/problem.php?id=2388
Solution
刚开始一看这不是分块水题吗?。。。卒。。。。mdzz
然后就发现没那么简单,还要维护动态的前缀和。。。
首先肯定是要分块的。。块里的a [ i ] 表示的都是1到 i 的前缀和。。
然后对于每个块,维护还未更新的前缀fir [ i ] 和未加上的值 p [ i ] 。。
然后询问的话。。发现会很麻烦。。。。。
首先最左右两块肯定直接暴力枚举,而整块内的显然不能在枚举了。。
发现对于块内的从左到右3点 A(x1,y1),B(x2,y2),C(x3,y3)若满足(y3-y1)/(x3-x1)>(y2-y1)/(x2-x1)
就可以舍去B点,因为无论 fir[ i ] 怎么变B点不会成为最优点。
证明:
若有y3 + x3*fir [ i ] - y2 - x2*fir [ i ] >= 0 那么显然B不是最优点。
否则 有 y3 + x3*fir [ i ] - y2 - x2*fir [ i ] < 0
那么说明 fir[ i ]满足 fir[ i ] < -(y3-y2) / (x3-x2)
那么y1+x1*fir[ i ] - y2 - x2*fir [ i ] > -(y1-y2)+(x1-x2)*( -(y3-y2) / (x3-x2) )
y1+x1*fir[ i ] - y2 - x2*fir [ i ] > ( (y2-y1)*(x3-x2)-(x1-x2)*(y3-y2) )/(x3-x2)
因为(y3-y1)/(x3-x1) - (y2-y1)/(x2-x1) > 0
而且(y3-y1)/(x3-x1) - (y2-y1)/(x2-x1) = (y2-y1)*(x3-x2)-(x1-x2)*(y3-y2)
所以( (y2-y1)*(x3-x2)-(x1-x2)*(y3-y2) )/(x3-x2) > 0
显然y1+x1*fir[ i ] - y2 - x2*fir [ i ]也大于0,B点也不是最优点
B点不是最优点得证。
所以只用单调栈维护这样一个凸包,询问时二分查找最大值即可。
代码
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<queue>
#include<vector>
#define N 100050
#define LL long long
using namespace std;
inline LL Read(){LL x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;
}
int n,Q,m,e,g[N];
LL inf=1LL<<60;
LL a[N],num[400],fir[400],p[400],q[400][400];
double slope(int x,int y){return (double)(a[x]-a[y])/(double)(x-y);
}
void reset(int k){int l=(k-1)*e+1,r=min(n,k*e),top=0;q[k][++top]=l;for(int i=l+1;i<=r;i++){while(top>=2 && slope(q[k][top-1],q[k][top])<slope(q[k][top-1],i)) top--;q[k][++top]=i;}q[k][0]=0;q[k][++top]=n+1;num[k]=top;
}
void pushdown(int k){int l=(k-1)*e+1,r=min(n,k*e);LL tmp=p[k];for(int i=l;i<=r;i++){tmp+=fir[k];a[i]+=tmp;}p[k]=fir[k]=0;
}
void update(int l,int r,LL w){LL tmp=0;if(g[l]==g[r]){pushdown(g[l]);for(int i=l;i<=r;i++) {tmp+=w;a[i]+=tmp;}for(int i=r+1;i<=min(g[r]*e,n);i++) a[i]+=tmp;for(int i=g[r]+1;i<=m;i++) p[i]+=tmp;reset(g[l]);return;}pushdown(g[l]);for(int i=l;i<=g[l]*e;i++) {tmp+=w;a[i]+=tmp;}reset(g[l]);for(int i=g[l]+1;i<g[r];i++){p[i]+=tmp;fir[i]+=w;tmp+=w*(LL)e;}pushdown(g[r]);for(int i=(g[r]-1)*e+1;i<=r;i++) {tmp+=w;a[i]+=tmp;}for(int i=r+1;i<=min(g[r]*e,n);i++) a[i]+=tmp;for(int i=g[r]+1;i<=m;i++) p[i]+=tmp;reset(g[r]);return;
}
LL calc(int x){return a[x]+p[g[x]]+fir[g[x]]*(LL)(x-(g[x]-1)*e);
}
LL get(int k){LL re1,re2,re3;int l=1,r=num[k];while(l<=r){int mid=(l+r)>>1;re1=calc(q[k][mid-1]);re2=calc(q[k][mid]);re3=calc(q[k][mid+1]);if(re1>re2 && re2>re3) r=mid;else if(re2>re1 && re3>re2) l=mid;else return re2;}
}
LL solve(int l,int r){LL re=-inf;if(g[l]==g[r]){for(int i=l;i<=r;i++) re=max(re,calc(i));return re;}for(int i=l;i<=g[l]*e;i++) re=max(re,calc(i));for(int i=(g[r]-1)*e+1;i<=r;i++) re=max(re,calc(i));for(int i=g[l]+1;i<g[r];i++) re=max(re,get(i));return re;
}
int main(){char ch;LL l,r,w;n=(int)Read();e=ceil(sqrt(n));for(int i=1;i<=n;i++) {a[i]=a[i-1]+Read();g[i]=(i+e-1)/e;}a[0]=a[n+1]=-inf;m=g[n];for(int i=1;i<=m;i++) reset(i);Q=Read();for(int i=1;i<=Q;i++){ch=getchar();while(ch!='0' && ch!='1') ch=getchar();if(ch=='0'){l=(int)Read();r=(int)Read();w=Read();update(l,r,w);}else {l=Read();r=Read();printf("%lld\n",solve(l,r));}}return 0;
}
This passage is made by Iscream-2001.
转载于:https://www.cnblogs.com/Yuigahama/p/8079722.html
BZOJ 2388--旅行规划(分块单调栈二分)相关推荐
- @bzoj - 2388@ 旅行规划
目录 @description@ @solution@ @accepted code@ @details@ @description@ 请你维护一个序列,支持两种操作: (1)某个区间 [x, y] ...
- 【分块】[LUOGU 旅行规划] 分块+二分+凸包优化
题目: 题目链接:[LUOGU 旅行规划] 题解: (由于这个,,我竟然还去写了二维凸包的模板题作为练习,,,然而,一点用都没有,,,,) 先解释一下题面的意思:就是一个区间加的操作,再加上一个区间的 ...
- bzoj 4237: 稻草人(CDQ分治+单调栈+二分)
4237: 稻草人 Time Limit: 40 Sec Memory Limit: 256 MB Submit: 1352 Solved: 594 [Submit][Status][Discus ...
- Loj#2880-「JOISC 2014 Day3」稻草人【CDQ分治,单调栈,二分】
正题 题目链接:https://loj.ac/problem/2880 题目大意 给出平面上的nnn个点,然后求有多少个矩形满足 左下角和右上角各有一个点 矩形之间没有其他点 1≤n≤2×105,1≤ ...
- 【Codeforces549F】Yura and Developers [单调栈][二分]
Yura and Developers Time Limit: 20 Sec Memory Limit: 512 MB Description Input Output Sample Input 4 ...
- 单调栈 or 线段树扫描线 ---- E. Delete a Segment [单调栈+二分] [扫描线处理空白位置的技巧乘2]
题目链接 题目大意: 给出nnn个线段代表集合,现在问若可以将其中任意一个线段删除,则能够形成最多多少个独立的集合(取并集后) 解题思路1: 首先我们先对线段按照起点排序 那么我们枚举删除的线段iii ...
- 【bzoj 2383】ballons(单调栈)
传送门biu~ 对于一个气球i,如果它左边的某个气球j的右边有比j大的气球,显然j不会对i的大小产生影响.所以能够影响气球i的大小的气球集合是坐标递增半径递减的. 我们把这些气球放在一个栈里,从栈顶的 ...
- Looksery Cup 2015 F. Yura and Developers(单调栈+二分+分治)(难*)
题目链接 题意:给定一个数组,问有多少区间满足:去掉最大值之后,和是k的倍数. 思路:日后补. #include<bits/stdc++.h> using namespace std; t ...
- BZOJ1767/Gym207383I CEOI2009 Harbingers 斜率优化、可持久化单调栈、二分
传送门--BZOJCH 传送门--VJ 注:本题在BZOJ上是权限题,在Gym里面也不能直接看,所以只能在VJ上交了-- 不难考虑到这是一个\(dp\). 设\(dep_x\)表示\(x\)在树上的带 ...
最新文章
- CV之FR:计算机视觉之人脸识别(Face Recognition)方向的简介、使用方法、案例应用之详细攻略
- 学术前沿 | DeepMind最新成果:图表示学习算法推理~46页ppt
- Linux系统使用GPT分区表方案推荐
- 排序归并连接Merge Sort Join
- Linux 2.6.39.1 Hello world 驱动总结
- ifconfig命令为centos linux系统配置临时的局域名IP、网关以及子网掩码
- 多看优秀的设计,时刻关注行业风向
- Java Spring-注解进行属性注入
- 2021-01-26数据治理具备哪些优势
- 【电子书】Head First Java
- 面试官:ca证书存储在哪的
- 数据库课程设计大作业大盘点【建议在校生收藏】
- 微信购物商城网站定制需要多少钱?电商网站建设开发方案(一)
- win10系统word2016出现错误 “429 ActiveX部件不能创建对象”
- C++ Primer 第五版 课后章节练习答案 第九章
- c语言中xml的解析方式,浅谈Xml的三种解析方式
- GMM 简介与 Stata 实现
- 软件测试员一定需要懂编程代码吗?
- ckplayer超酷flv网页播放器
- 200+JS功能 实例
热门文章
- JAVAWEB开发之Session的追踪创建和销毁、JSP详解(指令,标签,内置对象,动作即转发和包含)、JavaBean及内省技术以及EL表达式获取内容的使用
- ESP8266 Non-OS SDK开发探坑之四-用户非易失参数安全存储到flash
- 软件工程学习进度表9
- 北美18名校的数据挖掘及机器学习课程汇总
- 【多图】详谈进程与线程
- pytorch中的transforms.ToTensor和transforms.Normalize理解
- ps对比度调整的三种方法:ps自动对比度、色阶和曲线调整
- 微信小程序之历史百科软件
- html 点击加号展开代码,纯css实现加号一个的效果(代码示例)
- 中兴巨亏、华为巨奖的启示