2388: 旅行规划

Time Limit: 50 Sec  Memory Limit: 128 MB
Submit: 405  Solved: 118
[Submit][Status][Discuss]

Description

OIVillage是一个风景秀美的乡村,为了更好的利用当地的旅游资源,吸引游客,推动经济发展,xkszltl决定修建了一条铁路将当地n个最著名的经典连接起来,让游客可以通过火车从铁路起点(1号景点)出发,依次游览每个景区。为了更好的评价这条铁路,xkszltl为每一个景区都哦赋予了一个美观度,而一条旅行路径的价值就是它所经过的景区的美观度之和。不过,随着天气与季节的变化,某些景点的美观度也会发生变化。
xkszltl希望为每位旅客提供最佳的旅行指导,但是由于游客的时间有限,不一定能游览全部景区,然而他们也不希望旅途过于短暂,所以每个游客都希望能在某一个区间内的车站结束旅程,而xkszltl的任务就是为他们选择一个终点使得旅行线路的价值最大。可是当地的景点与前来观光的旅客实在是太多了,xkszltl无法及时完成任务,于是找到了准备虐杀NOI2011的你,希望你能帮助他完成这个艰巨的任务。

Input

第一行给出一个整数n,接下来一行给出n的景区的初始美观度。
第三行给出一个整数m,接下来m行每行为一条指令:
1.         0 x y k:表示将x到y这段铁路边上的景区的美观度加上k;
2.         1 x y:表示有一名旅客想要在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

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.

BZOJ 2388--旅行规划(分块&单调栈&二分)的更多相关文章

  1. BZOJ 2388: 旅行规划 [分块 凸包 等差数列]

    传送门 题意: 区间加和询问一段区间内整体前缀和的最大值 刚才还在想做完这道题做一道区间加等差数列结果发现这道就是.... 唯一的不同在于前缀和一段区间加上等差数列后,区间后面也要加上一个常数!!! ...

  2. BZOJ 2122 [分块+单调栈+二分](有详解)

    题面 传送门 给定序列d和lim.假设有一个初始价值\(x_0\),则经历第i天后价值变为\(min(x_0+d[i],lim[i])\),记\(f(i,j,x_0)\)表示以初始代价x0依次经过第i ...

  3. @bzoj - 2388@ 旅行规划

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 请你维护一个序列,支持两种操作: (1)某个区间 [x, y] ...

  4. bzoj 4709 [Jsoi2011]柠檬——单调栈二分处理决策单调性

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4709 题解:https://blog.csdn.net/neither_nor/articl ...

  5. 【bzoj5089】最大连续子段和 分块+单调栈维护凸包

    题目描述 给出一个长度为 n 的序列,要求支持如下两种操作: A  l  r  x :将 [l,r] 区间内的所有数加上 x : Q  l  r : 询问 [l,r] 区间的最大连续子段和. 其中,一 ...

  6. BZOJ1012: [JSOI2008]最大数maxnumber [线段树 | 单调栈+二分]

    1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 8748  Solved: 3835[Submi ...

  7. BZOJ1012最大数 [JSOI2008] 单调栈+二分

    正解:单调栈+二分查找(or,线段树? 解题报告: 拿的洛谷的链接quq 今天尝试学习了下单调栈,然后就看到有个博客安利了这个经典例题?于是就去做了,感觉还是帮助了理解趴quqqqqq 这题,首先,一 ...

  8. 51NOD 1962 区间计数 单调栈+二分 / 线段树+扫描线

     区间计数   基准时间限制:1.5 秒 空间限制:262144 KB 分值: 80   两个数列 {An} , {Bn} ,请求出Ans, Ans定义如下: Ans:=Σni=1Σnj=i[max{ ...

  9. 【bzoj4237】稻草人 分治+单调栈+二分

    题目描述 JOI村有一片荒地,上面竖着N个稻草人,村民们每年多次在稻草人们的周围举行祭典. 有一次,JOI村的村长听到了稻草人们的启示,计划在荒地中开垦一片田地.和启示中的一样,田地需要满足以下条件: ...

随机推荐

  1. Java Reference & ReferenceQueue一览

    Overview The java.lang.ref package provides more flexible types of references than are otherwise ava ...

  2. 简单API练手:(1)复制自身程序到windows目录和系统目录下;(2)获得系统的相关信息。

    1.复制自身程序到windows目录和系统目录下: #include <windows.h> #include <stdio.h> #include <string.h& ...

  3. 手游热更新方案xLua开源:Unity3D下Lua编程解决方案

    C#下Lua编程支持 xLua为Unity. .Net. Mono等C#环境增加Lua脚本编程的能力,借助xLua,这些Lua代码可以方便的和C#相互调用. xLua的突破 xLua在功能.性能.易用 ...

  4. ICG游戏:尼姆游戏异或解法的证明

    描述: 尼姆博奕(Nimm Game),有n堆石子,每堆石子有若干石子,两个人轮流从某一堆取任意多的物品,规定每次至少取一个,多者不限.取走最后石子的人获胜. 标准解法: 判断: 先计算先手是必胜还是 ...

  5. POJ1163 数学三角求最大路径

    描述:输入,行数,之后接数据,第一行一个数据,之后每行加一.5 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 思路:简单动态规划问题.dp[i][j]定义为到这个数为止(包括这个数)的最 ...

  6. 使用C#进行基于PI的开发

    首先欲基于PI-SDK开发PI数据库,必须先安装PI-SDK,然后再VS中新建了一个aspnet网站,添加引用:PI-SDK 1.2 Type Library 和 PISDKCommon 1.2 Ty ...

  7. nginx 负载均衡 使用ip_hash方式解决session问题 测试

    ip_hash的方式比较弱智,但是在一般情况下是挺有效的~~,如果能保证nginx是最上一层的代理,那么能够得到用户的ip是真实位置,就能做到负载,但是一家公司的所有员工其实走的是同一个ip,那么在这 ...

  8. MyEclipse不能自动编译解决办法总结

    yEclipse在debug模式下,有时会碰到修改的文件无法自动编译的问题,以下的方法可以逐一尝试一下. 1.确保:Project->build automatically 已经被选上. 2.p ...

  9. Djanjo 的app 模板路径 静态文件 完整版登录 新手三件套 以及orm

    一: django中app的概念: 一个项目可以包含多个应用(app,类似于模块,主页打开多个模块就是多个app) 创建了app,要在配置文件中注册 二:模板路径配置: 1 templates文件夹 ...

  10. UVaLive 4128 Steam Roller (多决策最短路)

    题意:给定一个图,r 根横线, c 根竖线.告诉你起点和终点,然后从起点走,每条边有权值,如果是0,就表示无法通行.走的规则是:如果你在下个路要转弯,会使这段路的时间加倍,但是如果一条路同时是这样,那 ...