比较神仙的一道dp,考试的时候还以为是打表找规律啥的。

我们重新描述一下这道题:一个10 9 × n的网格,每个格子有一个权值,每一列格子的权值都是相同的。从一个起点开始,每次可以向上走一格或者向左上角走一格,直到走到最上面一行为止,你需要最小化经过的格子的总权值。

然而我并没有看出来。

首先我们可以发现一些显然的性质,最优的路径之一一定形如:先往左上走若干步(可能不走),到达权值较小的一列后,一直往上走到顶。对于每个询问,枚举从起点出发最终会到达哪一列,就可以得到一个O(nq)的做法。

然而我也没有想到……

算了直接把作者的题解全放出来吧:

对于任意1 ≤ i ≤ j ≤ n, 从(x, j)出发最终到达第i列然后走到顶的代价,可以表示为一个关于x的一次函数,我们只关心这些一次函数的最小值,也就是这些直线形成的下凸壳。我们得到一个思路:将询问离线,按y从小到大排序,从最左边开始每次加入一条直线,维护下凸壳,然后在凸壳上二分即可得到答案。怎么维护下凸壳呢?对于一个点(x, y),它要么继承上一列x − 1的决策,要么就直接往上走到顶。并且我们发现,第二种情况只会出现在从顶端开始连续的一段中。于是我们只需要用栈维护凸壳即可。O((n + q) log n).

刚开始没怎么看懂,好像我的做法和题解也不是很一样,其实现在还有一些细节没有搞明白……

首先看暴力的式子:$ans=min(ans,sum[y(i)]-sum[j]+(x(i)-y(i)+j)*A[j])$

在y固定时,他是一个关于x的一次函数,即$y=kx+b$的形式,设走到j时停止然后向上走,那么$k=A[j],b=sum[y]-sum[j]+(j-y)*A[j]$

对于每一个j都是一条直线,那么这些直线构成了一个上凸壳。

我们可以用On的复杂度枚举y,用栈维护凸壳(添加直线是加在了坐标系的最左边),考虑y增加会给直线造成什么影响,只会使直线的截距发生改变而斜率不变,所以原来的凸壳仍然是对的。

那么考虑如何吧j=y的这条之间加入凸壳,首先将斜率大于这条直线的栈顶直线弹掉,然后交点也得是单调的,继续弹掉不合法的,(自己yy一下坐标系,横轴是询问的x,纵轴为最优解),

然后处理当前y的询问,直接二分栈找到当前x在坐标系中对应的直线就可以了(一定注意栈顶其实是坐标轴最左边的直线)。

放下代码(稍恶心):

 #include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define st sta[top]
#define sm sta[mid]
#define sm1 sta[mid+1]
#define st1 sta[top-1]
#define int LL
#define LL long long
using namespace std;
struct ques
{
int x,y,id;
#define x(i) que[i].x
#define y(i) que[i].y
#define id(i) que[i].id
friend bool operator < (ques a,ques b)
{return a.y<b.y;}
}que[];
int n,A[],q,maxx;
LL sum[],al[];
LL sta[],top;
double getx(int k1,int k2,int j1,int j2){return (double)(j2-j1)/(double)(k1-k2);}
inline int read();
signed main()
{
// freopen("function2.in","r",stdin);
// freopen("out.out","w",stdout); n=read();
for(int i=;i<=n;i++)A[i]=read(),sum[i]=sum[i-]+A[i];
q=read();
for(int i=;i<=q;i++)x(i)=read(),y(i)=read(),id(i)=i;
sort(que+,que+q+); int now=;
for(int y=;y<=n;y++)
{
while(top&&A[sta[top]]>=A[y])top--;
while(top>&&
getx(A[y],A[st],,sum[y]-sum[st]+A[st]*(st-y))
>=getx(A[st1],A[st],sum[y]-sum[st1]+A[st1]*(st1-y),sum[y]-sum[st]+A[st]*(st-y))
)top--;
sta[++top]=y;
for(;y(now)==y&&now<=q;now++)
{
int l=,r=top,mid;
while(l<r)
{
mid=(l+r)>>;
double tx=getx(A[sm],A[sm1],sum[y]-sum[sm]+A[sm]*(sm-y),sum[y]-sum[sm1]+A[sm1]*(sm1-y));
if(x(now)<=tx)l=mid+;
else r=mid;
}
mid=l;
al[id(now)]=sum[y]-sum[sm]+A[sm]*(x(now)-y+sm);
} }
for(int i=;i<=q;i++)printf("%lld\n",al[i]);
}
inline int read()
{
int s=,f=;char a=getchar();
while(a<''||a>''){if(a=='-')f=-;a=getchar();}
while(a>=''&&a<=''){s=s*+a-'';a=getchar();}
return s*f;
}

HZOJ Function的更多相关文章

  1. 通过百度echarts实现数据图表展示功能

    现在我们在工作中,在开发中都会或多或少的用到图表统计数据显示给用户.通过图表可以很直观的,直接的将数据呈现出来.这里我就介绍说一下利用百度开源的echarts图表技术实现的具体功能. 1.对于不太理解 ...

  2. jsp中出现onclick函数提示Cannot return from outside a function or method

    在使用Myeclipse10部署完项目后,原先不出错的项目,会有红色的叉叉,JSP页面会提示onclick函数错误 Cannot return from outside a function or m ...

  3. JavaScript function函数种类

    本篇主要介绍普通函数.匿名函数.闭包函数 目录 1. 普通函数:介绍普通函数的特性:同名覆盖.arguments对象.默认返回值等. 2. 匿名函数:介绍匿名函数的特性:变量匿名函数.无名称匿名函数. ...

  4. 在ubuntu16.10 PHP测试连接MySQL中出现Call to undefined function: mysql_connect()

    1.问题: 测试php7.0 链接mysql数据库的时候发生错误: Fatal error: Uncaught Error: Call to undefined function mysqli_con ...

  5. jquery中的$(document).ready(function() {});

    当文档载入时执行function函数里的代码, 这部分代码主要声明,页面加载后 "监听事件" 的方法.例如: $(document).ready( $("a") ...

  6. Function.prototype.toString 的使用技巧

    Function.prototype.toString这个原型方法可以帮助你获得函数的源代码, 比如: function hello ( msg ){ console.log("hello& ...

  7. 转:ORA-15186: ASMLIB error function = [asm_open], error = [1], 2009-05-24 13:57:38

    转:ORA-15186: ASMLIB error function = [asm_open], error = [1], 2009-05-24 13:57:38http://space.itpub. ...

  8. [Xamarin] 透過Native Code呼叫 JavaScript function (转帖)

    今天我們來聊聊關於如何使用WebView 中的Javascript 來呼叫 Native Code 的部分 首先,你得先來看看這篇[Xamarin] 使用Webview 來做APP因為這篇文章至少講解 ...

  9. Oracle数据库自动备份SQL文本:Procedure存储过程,View视图,Function函数,Trigger触发器,Sequence序列号等

    功能:备份存储过程,视图,函数触发器,Sequence序列号等准备工作:--1.创建文件夹 :'E:/OracleBackUp/ProcBack';--文本存放的路径--2.执行:create or ...

随机推荐

  1. 解决前端跨域请求(SpringBoot)

    @Configuration public class CorsConfig { private CorsConfiguration buildConfig() { CorsConfiguration ...

  2. JSP-response(HttpServletResponse)

    1 HttpServletResponse概述 2 Response 运行过程 3 通过抓包工具抓取Http响应 4 响应行 5 设置响应头 set  和add的区别 6 重定向 需要完成分析‘ 6 ...

  3. ROWID的使用——快速删除重复的记录

    ROWID是数据的详细地址,通过rowid,oracle可以快速的定位某行具体的数据的位置.ROWID可以分为物理rowid和逻辑rowid两种.普通的表中的rowid是物理rowid,索引组织表(I ...

  4. vue-eslint配置文件

    做项目的时候,我把eslint设置为了false,可想而知提交会产生的冲突 让我一个一个解决肯定不可能的,eslint的rule很多 在vue的配置文件.eslintrc.js中配置以下选项 这样只需 ...

  5. PHP获取真实客户端的真实IP的方法

    REMOTE_ADDR 是你的客户端跟你的服务器“握手”时候的IP.如果使用了“匿名代理”,REMOTE_ADDR将显示代理服务器的IP. HTTP_CLIENT_IP 是代理服务器发送的HTTP头. ...

  6. 洛谷 P1892 [BOI2003]团伙

    题目描述 1920年的芝加哥,出现了一群强盗.如果两个强盗遇上了,那么他们要么是朋友,要么是敌人.而且有一点是肯定的,就是: 我朋友的朋友是我的朋友: 我敌人的敌人也是我的朋友. 两个强盗是同一团伙的 ...

  7. mac pro 1.5T内存是如何实现的

    苹果发布全新Mac Pro:28核1.5T内存 预计售价10万+ 看到这样的新闻标题是不是很震撼,甚至怀疑人生,64位机怎么就可以1.5T内存了,自己的系统盘都没那么大 而且我们知道windows下的 ...

  8. Python学习笔记(三)字符串类型及其操作(2)

    1.字符串的表示 字符串是字符的序列表示,可以由一对单引号(‘).双引号(“)或三引号(’‘’)构成.其中,单引号.双引号和三引号都可以表示单行字符串,但是只有三引号可以表示多行字符串 在使用双引号时 ...

  9. php手册常用的函数

    <?php ************************************************************/ header("Content-type:tex ...

  10. 计算机网络 5.6-5.8 TCP/UDP

    来看看传输层的位置 要点: 传输层是为两个应用进程提供端到端的通信 传输层的复用和分用 传输层与应用层就是端口 (传输层的应用访问点 TSP) 传输层与网络层之间就是协议字段(网络层的 NTSP) 端 ...