[2019HDU多校第一场][HDU 6580][C. Milk]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6580
题目大意:\(n\times m\)大小的方格上有\(k\)瓶水,喝完每瓶水都需要一定的时间。初始点在\((1,1)\),每次可以向左或者向右走一步,如果当前的纵坐标为\(\frac{m+1}{2}\)则可以向下走一步。对所有的\(i \in [1,k]\),求喝恰好\(i\)瓶水需要花费的时间。\(n,m\leq 10^9, k\leq 10^4\)
题解:首先对瓶子的横坐标离散化处理,一行一行地更新答案。每到新的一行,先预处理出向左(右)走喝了\(i\)瓶水后,回到原点以及不回到原点所需要的最短时间,分别记为\(l,r,l\_back,r\_back\)。然后将左右两边合并,求出喝了\(i\)瓶水后,回到或不回到原点所需时间,记为\(g,g\_back\)。设\(f[i]\)为从\((1,1)\)出发,喝了\(i\)瓶水后回到当前行中点所需的最短时间,则这时就可以根据\(g\)来和之前的\(f[i]\)来更新答案,并用\(g\_back\)来更新\(f\)的值。时间复杂度为\(O(k^2)\)
对于每一行\(l,r,l\_back,r\_back\)数组的预处理,可以考虑先对喝水所需时间进行排序,枚举最远走到哪里。当最远到达的点确定后,就可以只考虑喝水所需要的时间来更新状态了
具体实现见代码,注意如果当前行为\(1\)时要特殊处理
#include<bits/stdc++.h>
using namespace std;
#define N 10005
#define LL long long
#define MP make_pair
LL T,n,m,k,f[N],ans[N];
LL l[N],l_back[N],r[N],r_back[N],g[N];
LL g_back[N],nxt[N];
pair<LL,LL>cost[N];
map<LL,vector<pair<LL,LL>>>mp;
void init()
{
mp.clear();
scanf("%lld%lld%lld",&n,&m,&k);
for(int i=;i<=k;i++)
f[i]=ans[i]=1e18;
for(int i=;i<=k;i++)
{
LL R,c,t;
scanf("%lld%lld%lld",&R,&c,&t);
mp[R].push_back(MP(c,t));
}
f[]=ans[]=m->>;
LL lst=,mx=;
for(const auto &pi:mp)
{
LL R=pi.first;
auto d=pi.second;
d.push_back(MP(,));
sort(d.begin(),d.end());
LL n=d.size()-,cnt=,mid=m+>>;
for(int i=;i<=n;i++)
if(d[i].first<mid)cnt++;
d[].first=mid;
if(R==)//对当前行为1的特判
{
nxt[]=;
for(int i=;i<=n;i++)
nxt[i]=i+,r[i]=r_back[i]=1e18;
for(int i=;i<=n;i++)
cost[i]=MP(d[i].second,i);
sort(cost+,cost+n+);
for(int i=n;i>=;i--)
{
LL sum=,id=;
for(int j=nxt[],k=;j<=n;j=nxt[j],k++)
{
sum+=cost[j].first;
r[k]=min(r[k],sum+d[i].first-);
if(nxt[j]<=n && cost[nxt[j]].second==i)id=j;
r_back[k]=min(r_back[k],sum+*max(d[i].first,mid)-mid-);
}
nxt[id]=nxt[nxt[id]];
}
for(int i=;i<=n;i++)
{
ans[i]=min(ans[i],r[i]);
f[i]=min(f[i],r_back[i]);
}
mx=n;
continue;
}
nxt[]=;
for(int i=;i<=cnt;i++)
{
cost[i]=MP(d[i].second,i);
l[i]=l_back[i]=1e18;
nxt[i]=i+;
}
sort(cost+,cost+cnt+);//对喝水耗时进行排序
for(int i=;i<=cnt;i++)//枚举最远走到哪,从远到近枚举
{
LL sum=,id=;
for(int j=nxt[],k=;j<=cnt;j=nxt[j],k++)//取前k小的喝水耗时,更新答案
{
sum+=cost[j].first;
l[k]=min(l[k],sum+mid-d[i].first);
if(nxt[j]<=cnt && cost[nxt[j]].second==i)id=j;
l_back[k]=min(l_back[k],sum+*(mid-d[i].first));
}
nxt[id]=nxt[nxt[id]];//删除当前最远点
}
nxt[cnt]=cnt+;
for(int i=cnt+;i<=n;i++)
{
cost[i]=MP(d[i].second,i);
r[i-cnt]=r_back[i-cnt]=1e18;
nxt[i]=i+;
}
sort(cost+cnt+,cost+n+);
for(int i=n;i>cnt;i--)
{
LL sum=,id=cnt;
for(int j=nxt[cnt],k=;j<=n;j=nxt[j],k++)
{
sum+=cost[j].first;
r[k]=min(r[k],sum+d[i].first-mid);
if(nxt[j]<=n && cost[nxt[j]].second==i)id=j;
r_back[k]=min(r_back[k],sum+*(d[i].first-mid));
}
nxt[id]=nxt[nxt[id]];
}
for(int i=;i<=n;i++)//合并l, r
{
g[i]=g_back[i]=1e18;
for(int j=max(0ll,i-(n-cnt));j<=min(1ll*i,cnt);j++)
{
g[i]=min(g[i],min(l[j]+r_back[i-j],l_back[j]+r[i-j]));
g_back[i]=min(g_back[i],min(l_back[j]+r_back[i-j],l_back[j]+r_back[i-j]));
}
}
for(int i=;i<=mx;i++)//更新ans
{
f[i]+=R-lst;//先加上走过的行数
for(int j=;j<=n;j++)
ans[i+j]=min(ans[i+j],f[i]+g[j]);
}
for(int i=mx;i>=;i--)//更新f
for(int j=n;j>=;j--)
f[i+j]=min(f[i+j],f[i]+g_back[j]);
mx+=n,lst=R;//更新上一次走到的行数
}
for(int i=;i<=k;i++)
printf("%lld%c",ans[i],i<k?' ':'\n');
}
int main()
{
scanf("%lld",&T);
while(T--)init();
}
[2019HDU多校第一场][HDU 6580][C. Milk]的更多相关文章
- [2019HDU多校第一场][HDU 6578][A. Blank]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6578 题目大意:长度为\(n\)的数组要求分别填入\(\{0,1,2,3\}\)四个数中的任意一个,有 ...
- [2019HDU多校第一场][HDU 6584][G. Meteor]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6584 题目大意:求所有满足\(0<\frac{p}{q}\leq1, gcd(p,q)=1,p\ ...
- [2019HDU多校第一场][HDU 6590][M. Code]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6590 题目大意(来自队友):二维平面上有\(n\)个点,每个点要么是黑色要么是白色,问能否找到一条直线 ...
- [2019HDU多校第一场][HDU 6588][K. Function]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6588 题目大意:求\(\sum_{i=1}^{n}gcd(\left \lfloor \sqrt[3] ...
- 2019HDU多校第一场1001 BLANK (DP)(HDU6578)
2019HDU多校第一场1001 BLANK (DP) 题意:构造一个长度为n(n<=10)的序列,其中的值域为{0,1,2,3}存在m个限制条件,表示为 l r x意义为[L,R]区间里最多能 ...
- [2019HDU多校第二场][HDU 6591][A. Another Chess Problem]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6591 题目大意:二维坐标系上,所有满足\(5|2x+y\)的点都被设为障碍物,无法通过.现给出一对点, ...
- 2019HDU多校第一场 BLANK DP
题意:有四种数字,现在有若干个限制条件:每个区间中不同的数字种类必须是多少种,问合法的方案数. 思路: 定义 dp[i][j][k][t] 代表填完前 t 个位置后,{0,1,2,3} 这 4 个数字 ...
- 2019HDU多校第一场 String 贪心
题意:给你一个字符串,问是否存在一个长度为m的子序列,子序列中对应字符的数目必须在一个范围内,问是否存在这样的字符串?如果存在,输出字典序最小的那个. 思路:贪心,先构造一个序列自动机,序列自动机指向 ...
- 2019HDU多校第一场 6582 Path 【最短路+最大流最小割】
一.题目 Path 二.分析 首先肯定要求最短路,然后如何确定所有的最短路其实有多种方法. 1 根据最短路,那么最短路上的边肯定是可以满足$dist[from] + e.cost = dist[to] ...
随机推荐
- Paypal、Stripe、Braintree,跨境电商金流第三方支付该用哪家?
在台湾做跨境电子商务生意,电商网站的金流肯定是一个最大的麻烦,Paypal或是Stripe和Braintree则是国际上大家最常用的金流整合第三方支付服务商.这些金流服务大幅简化网站付费过程,都让消费 ...
- 并发艺术--java并发机制的底层实现原理
前言 Java代码在编译后会变成Java字节码,字节码被类加载器加载到JVM里,JVM执行字节码,最终需要转化为汇编指令在CPU上执行,Java中所使用的并发机制依赖于JVM的实现和CPU的指令. 一 ...
- JDBC 注册驱动,获取连接
jdbc 动力节点视频教程 JDBC编程六步 1.注册驱动(作用:告诉Java程序,即将要连接的是哪个品牌的数据库) 2.获取连接 (表示JVM进程和数据库进程之间的通道打开了,属于进程间的通信,重量 ...
- @ConfigurationProperties和@Value的区别
@ConfigurationProperties @Value 功能: 批量注入配置文件中的属性 一个个指定,多个属性多个@Value 松散绑定: 支持 不支持 SpEL: 不支持 支持 JSR ...
- LIUNX随堂学习-2 用户和组,增、删、改、查
1.less的使用 less /etc/group #查看组的信息 less /etc/gshadow #查看组密码 例如:less /tmp/aa ...
- Vue起飞前的准备
Vue起飞前的准备 一.什么是ECMAScript,以及es6的诞生? 1997年 ECMAScript 1.0 诞生 1999年12月 ECMAScript 3.0诞生,它 是一个巨大的成功,在业界 ...
- Scratch-介绍“克隆”
上次我们模仿一个扔小球的运动, 用到了Scratch的“克隆”. 用Scratch模仿扔小球 “克隆”命令 Scratch“克隆”有三个命令积木. 区分“本体”和“克隆体” 使用“克隆”命令, 我们发 ...
- Python3 使用pygal 生成世界人口地图
最近在看<python从入门到实践>,其中有一个例子是使用pygal制作世界人口地图,觉得挺有意思的,这里就记录下来了, 其实代码不是很复杂,使用环境环境python3.废话不多说,直接上 ...
- 游记-pkupc&cts2019
Day0 和boshi.Rayment组的队,昨天听学长说这次比赛可以加学分,他们信科的大部分人都会参加,估摸有两百多支队伍--然而奖品只有不到一百份 我要奖品呐! 上午十一点半到的北京,拉着行李提着 ...
- css border 三角形阴影(不规则图形阴影) & 多重边框的制作
前言:这是笔者学习之后自己的理解与整理.如果有错误或者疑问的地方,请大家指正,我会持续更新! border 的组合写法 border:border-width border-style border- ...