#dp or 贪心+堆#CF704B Ant Man
分析(dp)
考虑到对于一个排列单独抽出 \(1\sim i\) 可能会分成若干段,而贡献一定是固定的,不会影响之后的选择。
首先 \(a,c\) 加上 \(x\),\(b,d\) 减去 \(x\),那么贡献就转换为
\(\begin{cases}i<j,d_i+a_j\\i>j,c_i+b_j\end{cases}\)
同样考虑从小到大插入每一个数,
设 \(dp[i][j]\) 表示前 \(i\) 个数分成 \(j\) 段的最小权值。
若 \(i=St\),那么可以新开一段或者补到开头位置。
\(dp[i][j]=\min\{dp[i-1][j-1]+d_i,dp[i-1][j]+c_i(j>0)\}\)
若 \(i=Ed\),同理 \(dp[i][j]=\min\{dp[i-1][j-1]+b_i,dp[i-1][j]+a_i(j>0)\}\)
如果 \(i\) 不为开头或结尾,那么可以新开一段,合并两段,或者接在一段的开头或者结尾(但是不能替代 \(St\) 和 \(Ed\))
新开一段就是 \(dp[i][j]=\min\{dp[i-1][j-1]+b_i+d_i\}\)
合并两段就是 \(dp[i][j]=\min\{dp[i-1][j+1]+a_i+c_i\}\)
接到开头就是 \(dp[i][j]=\min\{dp[i-1][j]+b_i+c_i\}(j>(i>St))\)
接到末尾就是 \(dp[i][j]=\min\{dp[i-1][j]+a_i+d_i\}(j>(i>Ed))\)
最后答案就是 \(dp[n][1]\)
代码
#include <cstdio>
#include <cctype>
#include <cstring>
using namespace std;
const int N=5011; typedef long long lll;
int n,st,ed,x[N],a[4][N]; lll dp[2][N];
int iut(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
void Min(lll &x,lll y){x=x<y?x:y;}
int main(){
n=iut(),st=iut(),ed=iut();
for (int i=1;i<=n;++i) x[i]=iut();
for (int i=1;i<=n;++i) a[0][i]=iut()+x[i];
for (int i=1;i<=n;++i) a[1][i]=iut()-x[i];
for (int i=1;i<=n;++i) a[2][i]=iut()+x[i];
for (int i=1;i<=n;++i) a[3][i]=iut()-x[i];
memset(dp[0],0x3f,sizeof(dp[0])),dp[0][0]=0;
for (int i=1;i<=n;++i){
memset(dp[i&1],0x3f,sizeof(dp[i&1]));
if (i==st){
for (int j=(i>ed);j<i;++j){
if (j) Min(dp[i&1][j],dp[(i&1)^1][j]+a[2][i]);
Min(dp[i&1][j+1],dp[(i&1)^1][j]+a[3][i]);
}
}else if (i==ed){
for (int j=(i>st);j<i;++j){
if (j) Min(dp[i&1][j],dp[(i&1)^1][j]+a[0][i]);
Min(dp[i&1][j+1],dp[(i&1)^1][j]+a[1][i]);
}
}else{
for (int j=(i>st)+(i>ed);j<i;++j){
if (j>1) Min(dp[i&1][j-1],dp[(i&1)^1][j]+a[0][i]+a[2][i]);
Min(dp[i&1][j+1],dp[(i&1)^1][j]+a[1][i]+a[3][i]);
if (j>(i>st)) Min(dp[i&1][j],dp[(i&1)^1][j]+a[2][i]+a[1][i]);
if (j>(i>ed)) Min(dp[i&1][j],dp[(i&1)^1][j]+a[0][i]+a[3][i]);
}
}
}
return !printf("%lld",dp[n&1][1]);
}
分析(贪心)
首先填入首尾,为了有最小值出现,同时将 1 填入。
还是一样从小到大填数,不过先考虑加上 \(a_i+c_i\),
其它数必然是接在中间,考虑直接用选完的数接上,
那么就是要找到 \(b_i-a_i\) 或者是 \(d_i-c_i\) 的最小值,用堆维护即可。
代码
#include <cstdio>
#include <cctype>
#include <cstring>
using namespace std;
const int N=5011; typedef long long lll;
int n,st,ed,x[N],Cnt; lll ans,heap[N<<1],a[4][N];
int iut(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
void Swap(lll &x,lll &y){x^=y^=x^=y;}
void Push(lll W){
heap[++Cnt]=W;
for (int x=Cnt;x>1;x>>=1)
if (heap[x]<heap[x>>1])
Swap(heap[x],heap[x>>1]);
else return;
}
void Pop(){
heap[1]=heap[Cnt--];
for (int x=1;(x<<1)<=Cnt;){
int y=x<<1|1;
if (y>Cnt||heap[y]>=heap[y-1]) --y;
if (heap[x]<=heap[y]) return;
Swap(heap[x],heap[y]),x=y;
}
}
int main(){
n=iut(),st=iut(),ed=iut();
for (int i=1;i<=n;++i) x[i]=iut();
for (int i=1;i<=n;++i) a[0][i]=iut()+x[i];
for (int i=1;i<=n;++i) a[1][i]=iut()-x[i];
for (int i=1;i<=n;++i) a[2][i]=iut()+x[i];
for (int i=1;i<=n;++i) a[3][i]=iut()-x[i];
if (st>1&&ed>1) ans=a[2][st]+a[1][1]+a[3][1]+a[0][ed];
else ans=(st>ed)?(a[2][st]+a[1][ed]):(a[3][st]+a[0][ed]);
for (int i=2;i<=n;++i)
if (i==st) Push(a[3][i]-a[2][i]);
else if (i==ed) Push(a[1][i]-a[0][i]);
else{
ans+=a[0][i]+a[2][i];
if (i<st) Push(a[1][i]-a[0][i]);//可以与st接在一起
if (i<ed) Push(a[3][i]-a[2][i]);//可以与ed接在一起
ans+=heap[1],Pop();
if (i>st) Push(a[1][i]-a[0][i]);
if (i>ed) Push(a[3][i]-a[2][i]);
}
return !printf("%lld",ans);
}
#dp or 贪心+堆#CF704B Ant Man的更多相关文章
- 洛谷 P4437 [HNOI/AHOI2018]排列(贪心+堆,思维题)
题面传送门 开始 WA ycx 的遗产(bushi 首先可以将题目转化为图论模型:\(\forall i\) 连边 \(a_i\to i\),然后求图的一个拓扑序 \(b_1,b_2,\dots b_ ...
- 【贪心+堆】XMU 1584 小明的烦恼
题目链接: http://acm.xmu.edu.cn/JudgeOnline/problem.php?id=1584 题目大意: 给n(n<=100 000)个任务的耗时和截至时间,问最少不能 ...
- BZOJ_2151_种树_贪心+堆+链表
BZOJ_2151_种树_贪心+堆 Description A城市有一个巨大的圆形广场,为了绿化环境和净化空气,市政府决定沿圆形广场外圈种一圈树.园林部门得到指令后,初步规划出n个种树的位置,顺时针编 ...
- BZOJ_2006_[NOI2010]超级钢琴_贪心+堆+ST表
BZOJ_2006_[NOI2010]超级钢琴_贪心+堆+ST表 Description 小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的 音乐 ...
- BZOJ_1029_ [JSOI2007]建筑抢修_贪心+堆
BZOJ_1029_ [JSOI2007]建筑抢修_贪心+堆 Description 小刚在玩JSOI提供的一个称之为“建筑抢修”的电脑游戏:经过了一场激烈的战斗,T部落消灭了所有z部落的入侵者.但是 ...
- 【bzoj4425】[Nwerc2015]Assigning Workstations分配工作站 贪心+堆
题目描述 佩内洛普是新建立的超级计算机的管理员中的一员. 她的工作是分配工作站给到这里来运行他们的计算研究任务的研究人员. 佩内洛普非常懒惰,不喜欢为到达的研究者们解锁机器. 她可以从在她的办公桌远程 ...
- 【bzoj1029】[JSOI2007]建筑抢修 贪心+堆
题目描述 小刚在玩JSOI提供的一个称之为“建筑抢修”的电脑游戏:经过了一场激烈的战斗,T部落消灭了所有z部落的入侵者.但是T部落的基地里已经有N个建筑设施受到了严重的损伤,如果不尽快修复的话,这些建 ...
- 【bzoj2802】[Poi2012]Warehouse Store 贪心+堆
题目描述 有一家专卖一种商品的店,考虑连续的n天.第i天上午会进货Ai件商品,中午的时候会有顾客需要购买Bi件商品,可以选择满足顾客的要求,或是无视掉他.如果要满足顾客的需求,就必须要有足够的库存.问 ...
- BZOJ 1724: [Usaco2006 Nov]Fence Repair 切割木板 贪心 + 堆 + 反向思考
Description Farmer John想修理牧场栅栏的某些小段.为此,他需要N(1<=N<=20,000)块特定长度的木板,第i块木板的长度为Li(1<=Li<=50, ...
- P1095 守望者的逃离——DP?贪心?
https://www.luogu.org/problem/P1095 恶魔猎手尤迪安野心勃勃,他背叛了暗夜精灵,率领深藏在海底的娜迦族企图叛变.守望者在与尤迪安的交锋中遭遇了围杀,被困在一个荒芜的大 ...
随机推荐
- lock锁,Semaphore信号量,Event事件,进程队列Queue,生产者消费者模型,JoinableQueue---day31
1.lock锁 # ### 锁 lock from multiprocessing import Process,Lock import json,time # (1) lock的基本语法 " ...
- gin框架中的c.Next()/c.Abort()
package main import ( "fmt" "github.com/gin-gonic/gin" ) func func1(c *gin.Conte ...
- Spring-Cloud集成redis-cluster
前言 系统之前接入的是单点redis,为了条系统高可用能力,特增加集成redis-cluster集群的步骤 依赖库引入 <dependency> <groupId>org.sp ...
- FROM_UNIXTIME函数格式化时间戳日期类型
select FROM_UNIXTIME(bce.daysec_time/1000,'%Y-%m-%d %h:%i:%s') ,bce.* from biz_cvent bce where bce.d ...
- 浅入ABP(2):添加基础集成服务
浅入ABP(2):添加基础集成服务 版权护体作者:痴者工良,微信公众号转载文章需要 <NCC开源社区>同意. 目录 浅入ABP(2):添加基础集成服务 定义一个特性标记 全局统一消息格式 ...
- 通过keil内置标准库创建stm32工程
通过keil内置标准库创建stm32工程.md body { font-family: var(--vscode-markdown-font-family, -apple-system, BlinkM ...
- 浅析图数据库 Nebula Graph 数据导入工具——Spark Writer
从 Hadoop 说起 近年来随着大数据的兴起,分布式计算引擎层出不穷.Hadoop 是 Apache 开源组织的一个分布式计算开源框架,在很多大型网站上都已经得到了应用.Hadoop 的设计核心思想 ...
- 为什么带NOLOCK的查询语句还会造成阻塞
背景 客户反映HIS数据库在11点出现了长时间的阻塞,直到手动KILL掉阻塞的源头.请我们协助分析原因,最终定位到.NET程序中使用的SqlDataReader未正常关闭导致. 现象 登录SQL专家云 ...
- 使用Order By NULL 解决 group by后自动排序,优化Sql性能
使用Order By NULL 解决 group by后自动排序,优化Sql性能 对于 Group by 后的结果,Mysql搜索引擎会将结果按照Group by 的字段按照升序,自动排序,例如: t ...
- Educational Codeforces Round 145 (Rated for Div. 2)C. Sum on Subarrays(构造)
很意思的一道构造题 题意:给一个\(n.k\),让构造长度为n的数组满足,子数组为整数的个数为k个,负数的为\(k-(n+1)* n/2\),每个数的范围为\([-1000,1000]\) 这种构造题 ...