正题

题目链接:https://www.luogu.com.cn/problem/P7294


题目大意

\(n\times m\)的网格,当你在\((x,y)\)时你有两种选择

  1. 花费\(x^2\)的代价向右移动
  2. 花费\(c_y\)的代价向下移动

\(q\)次询问\((1,1)\)走到\((x,y)\)的最小代价。

\(1\leq n\leq 10^9,1\leq m,q\leq 2\times 10^5\)


解题思路

假设我们开始都是直接走最上面向右的路(也就是代价都是\(1^2\))。

然后考虑在某个位置\((x,y)\)要走到\((n,m)\)时向下走会产生的贡献为\(c_y+(m-y)\times (2x+1)\)(后面要抬\(m-y\)个横着走,然后从\(x^2\)到\((x+1)^2\)要到加\(2x+1\))。

然后拆一下就是\(c_y+m-y+2xm-2xy\)。发现斜率\(-2y\)是按照\(y\)递增递减的,而且我们要求选出的若干个\(c_y\)的\(y\)一定要递增,但是这样的话我们选出来的一定是递增的所以我们只需要考虑对于每个\(x\)选择一个\(y\)使得最小化\(c_y+(m-y)\times (2x+1)\)。

按照询问排序,一个一个加入新的\(c_y\),按照斜率维护一个上凸壳,然后在凸壳上面二分就好了。

时间复杂度\(O(m+q\log m)\)


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=2e5+10;
struct node{
ll n,m,id;
}q[N];
ll n,m,t,top,b[N],k[N],s[N],sum[N],l[N],r[N],ans[N];
ll calc(ll i,ll j)//i<j
{return (b[j]-b[i]+k[i]-k[j]-1)/(k[i]-k[j]);}
ll cap(ll i,ll j){
ll x=calc(i,j);
if(x<=l[i])return 1;
return 0;
}
ll getf(ll x,ll l,ll r)
{return (r+l)*(r-l+1)/2*k[x]+b[x]*(r-l+1);}
bool cmp(node x,node y)
{return x.m<y.m;}
signed main()
{
// freopen("data.in","r",stdin);
// freopen("data.out","w",stdout);
scanf("%lld%lld",&n,&m);
for(ll i=1;i<=m;i++){
scanf("%lld",&b[i]);
b[i]=b[i]-i;k[i]=2*(-i);
}
scanf("%lld",&t);
for(ll i=1;i<=t;i++){
scanf("%lld%lld",&q[i].n,&q[i].m);
q[i].id=i;
}
sort(q+1,q+1+t,cmp);
for(ll i=1,z=1;i<=m;i++){
r[i]=n;
while(top>0&&cap(s[top],i))top--;
if(top)l[i]=max(calc(s[top],i),1ll);else l[i]=1;
if(l[i]<=r[i]){
r[s[top]]=l[i]-1;s[++top]=i;
sum[top-1]=((top>1)?sum[top-2]:0)+getf(s[top-1],l[s[top-1]],r[s[top-1]]);
sum[top]=sum[top-1]+getf(i,l[i],r[i]);
}
while(z<=t&&q[z].m<=i){
ll qn=q[z].n-1,L=1,R=top;
while(L<=R){
ll mid=(L+R)>>1;
if(r[s[mid]]<qn)L=mid+1;
else R=mid-1;
}
ans[q[z].id]=sum[L-1]+getf(s[L],l[s[L]],qn)+(qn+1)*qn*i+i*qn+i-1;
z++;
}
}
for(ll i=1;i<=t;i++)
printf("%lld\n",ans[i]);
return 0;
}

P7294-[USACO21JAN]Minimum Cost Paths P【单调栈】的更多相关文章

  1. [Agc005D/At2060] Minimum Sum - 单调栈

    鉴于早上那题让我怀疑单调栈白学,特意来复习下单调栈 题意 考虑按照每个元素对答案的贡献来统计,那么我们只需要找到每个元素左边右边第一个比它小的就可 这题给的又是排列,简直不能再良心 #include ...

  2. CodeForces 548D 单调栈

    Mike and Feet Time Limit:1000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Subm ...

  3. HDOJ 4252 A Famous City 单调栈

    单调栈: 维护一个单调栈 A Famous City Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (J ...

  4. Codeforces548D:Mike and Feet(单调栈)

    Mike is the president of country What-The-Fatherland. There are n bears living in this country besid ...

  5. Imbalanced Array CodeForces - 817D (思维+单调栈)

    You are given an array a consisting of n elements. The imbalance value of some subsegment of this ar ...

  6. Educational Codeforces Round 23 D. Imbalanced Array 单调栈

    D. Imbalanced Array time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  7. 【CF671E】Organizing a Race 单调栈+线段树

    [CF671E]Organizing a Race 题意:n个城市排成一排,每个城市内都有一个加油站,赛车每次经过第i个城市时都会获得$g_i$升油.相邻两个城市之间由道路连接,第i个城市和第i+1个 ...

  8. spoj MINSUB 单调栈+二分

    题目链接:点击传送 MINSUB - Largest Submatrix no tags  You are given an matrix M (consisting of nonnegative i ...

  9. Codeforces Round #305 (Div. 1) B. Mike and Feet 单调栈

    B. Mike and Feet Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/547/pro ...

随机推荐

  1. GitLabRunner命令

    启动命令 gitlab-runner --debug <command> #调试模式排查错误特别有用. gitlab-runner <command> --help #获取帮助 ...

  2. Spring-boot注入配置为java静态属性

    配置文件 注入静态变量 注意 类上面有:@Component注解 使用注入的静态变量 成功

  3. linux 的删除

    1,删除 命令行 rm -rf 文件夹名称 2,下载 wget 网址 -------------------- 查找ES进程号 ps -ef | grep elastic kill -9 3250 3 ...

  4. wpf实现轮播效果

    在web上面轮播非常常见 WPF中似乎要自己搞,那么我依葫芦画瓢搞一个 如下,平时按一定的时间轮播,点击右下角的灰色圆点(不是很明显0.0),则切换到对应图片  先放 源码:https://gitee ...

  5. 【IDE】Sublime Text 3 使用配置

    1 安装 首先现在安装Sublime Text 3,直接官网下载(http://www.sublimetext.com/3),也可以在其他地方下载,安装完成后进行破解 菜单栏Help - Enter ...

  6. Jemeter压力测试

    Jmeter教程 简单的压力测试 Jmeter是一个非常好用的压力测试工具.  Jmeter用来做轻量级的压力测试,非常合适,只需要十几分钟,就能把压力测试需要的脚本写好. 转载自小坦克:https: ...

  7. 并发编程之:synchronized

    大家好,我是小黑,一个在互联网苟且偷生的农民工. 之前的文章中跟大家分享了关于Java中线程的一些概念和基本的使用方法,比如如何在Java中启动一个线程,生产者消费者模式等,以及如果要保证并发情况下多 ...

  8. MySQL基础——常用命令

    一.连接MySQL 1.启动mysql首先在打开cmd窗口,输入mysql -uroot -p ,然后空格进入MySQL控制台,MySQL的提示符是: mysql>. mysql -uroot ...

  9. springboot系列总结(二)---springboot的常用注解

    上一篇文章我们简单讲了一下@SpringBootApplication这个注解,申明让spring boot自动给程序进行必要的配置,他是一个组合注解,包含了@ComponentScan.@Confi ...

  10. Linux从头学10:三级跳过程详解-从 bootloader 到 操作系统,再到应用程序

    作 者:道哥,10+年的嵌入式开发老兵. 公众号:[IOT物联网小镇],专注于:C/C++.Linux操作系统.应用程序设计.物联网.单片机和嵌入式开发等领域. 公众号回复[书籍],获取 Linux. ...